testing swaps
This commit is contained in:
parent
c4644b5701
commit
0097dcc46c
8 changed files with 858 additions and 15 deletions
10
env.example
10
env.example
|
|
@ -14,8 +14,14 @@
|
|||
# A trusted peer that will hold a node-level account until channel automation becomes affordable
|
||||
# The developer is used by default or you may specify your own
|
||||
# To disable this feature entirely overwrite the env with "null"
|
||||
#LIQUIDITY_PROVIDER_PUB=null
|
||||
#DISABLE_LIQUIDITY_PROVIDER=false
|
||||
# LIQUIDITY_PROVIDER_PUB=null
|
||||
# DISABLE_LIQUIDITY_PROVIDER=false
|
||||
# USE_ONLY_LIQUIDITY_PROVIDER=false
|
||||
|
||||
#SWAPS
|
||||
# BOLTZ_HTTP_URL=
|
||||
# BOLTZ_WEBSOCKET_URL=
|
||||
# ENABLE_SWAPS=false
|
||||
|
||||
#DB
|
||||
#DATABASE_FILE=db.sqlite
|
||||
|
|
|
|||
480
package-lock.json
generated
480
package-lock.json
generated
|
|
@ -18,10 +18,13 @@
|
|||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^17.0.31",
|
||||
"@types/secp256k1": "^4.0.3",
|
||||
"@vulpemventures/secp256k1-zkp": "^3.2.1",
|
||||
"axios": "^1.9.0",
|
||||
"bech32": "^2.0.0",
|
||||
"better-sqlite3": "^12.2.0",
|
||||
"bitcoin-core": "^4.2.0",
|
||||
"bitcoinjs-lib": "^6.1.7",
|
||||
"boltz-core": "^3.0.0",
|
||||
"chai": "^4.3.7",
|
||||
"chai-string": "^1.5.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
|
|
@ -29,6 +32,7 @@
|
|||
"csv": "^6.3.8",
|
||||
"dotenv": "^16.4.5",
|
||||
"eccrypto": "^1.1.6",
|
||||
"ecpair": "^3.0.0",
|
||||
"express": "^4.21.2",
|
||||
"globby": "^13.1.2",
|
||||
"grpc-tools": "^1.12.4",
|
||||
|
|
@ -40,6 +44,7 @@
|
|||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.5.5",
|
||||
"secp256k1": "^5.0.1",
|
||||
"tiny-secp256k1": "^2.2.4",
|
||||
"ts-node": "^10.7.0",
|
||||
"ts-proto": "^1.131.2",
|
||||
"typeorm": "^0.3.26",
|
||||
|
|
@ -68,6 +73,12 @@
|
|||
"typescript": "5.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@boltz/bitcoin-ops": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@boltz/bitcoin-ops/-/bitcoin-ops-2.0.0.tgz",
|
||||
"integrity": "sha512-AM7vFNwSD7B4XI6yeRKccWbbD/lvwoFr8U3pqhzryBQo4uMkYe5V3/kMVnml4SNuxzyqdIFu4ur3TId02sC33A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@bufbuild/protobuf": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.7.0.tgz",
|
||||
|
|
@ -441,6 +452,12 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@openzeppelin/contracts": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.4.0.tgz",
|
||||
"integrity": "sha512-eCYgWnLg6WO+X52I16TZt8uEjbtdkgLC0SUX/xnAksjjrQI4Xfn4iBRoI5j55dmlOhDv1Y7BoR3cU7e3WWhC6A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
|
|
@ -1012,6 +1029,16 @@
|
|||
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/randombytes": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/randombytes/-/randombytes-2.0.3.tgz",
|
||||
"integrity": "sha512-+NRgihTfuURllWCiIAhm1wsJqzsocnqXM77V/CalsdJIYSRGEHMnritxh+6EsBklshC+clo1KgnN14qgSGeQdw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
|
||||
|
|
@ -1112,6 +1139,18 @@
|
|||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@vulpemventures/secp256k1-zkp": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@vulpemventures/secp256k1-zkp/-/secp256k1-zkp-3.2.1.tgz",
|
||||
"integrity": "sha512-2U4nuNbXuUgMmxhuoILbRMoD2DE7KND3udk5cYilIS1MHvMtje9ywUm/zsI0g7d7x8g2A57xri+wvqCC/fCnJg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"long": "^5.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
|
|
@ -1684,6 +1723,12 @@
|
|||
"license": "Apache-2.0",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/base-x": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz",
|
||||
"integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
|
|
@ -1764,12 +1809,54 @@
|
|||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bip174": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz",
|
||||
"integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bip174-liquid": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bip174-liquid/-/bip174-liquid-1.0.3.tgz",
|
||||
"integrity": "sha512-e69sC0Cq2tBJuhG2+wieXv40DN13YBR/wbIjZp4Mqwpar5vQm8Ldqijdd6N33XG7LtfvQi/zKm5fSzdPY/9mgw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bip32": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz",
|
||||
"integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.2.0",
|
||||
"@scure/base": "^1.1.1",
|
||||
"typeforce": "^1.11.5",
|
||||
"wif": "^2.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bip65": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bip65/-/bip65-1.0.3.tgz",
|
||||
"integrity": "sha512-RQ1nc7xtnLa5XltnCqkoR2zmhuz498RjMJwrLKQzOE049D1HUqnYfon7cVSbwS5UGm0/EQlC2CH+NY3MyITA4Q==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bip66": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz",
|
||||
"integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
|
|
@ -1792,6 +1879,71 @@
|
|||
"node": ">=7"
|
||||
}
|
||||
},
|
||||
"node_modules/bitcoinjs-lib": {
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz",
|
||||
"integrity": "sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.2.0",
|
||||
"bech32": "^2.0.0",
|
||||
"bip174": "^2.1.1",
|
||||
"bs58check": "^3.0.1",
|
||||
"typeforce": "^1.11.3",
|
||||
"varuint-bitcoin": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bitcoinjs-lib/node_modules/base-x": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz",
|
||||
"integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bitcoinjs-lib/node_modules/bs58": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz",
|
||||
"integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base-x": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bitcoinjs-lib/node_modules/bs58check": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz",
|
||||
"integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.2.0",
|
||||
"bs58": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bitcoinjs-lib/node_modules/varuint-bitcoin": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz",
|
||||
"integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/bitset": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/bitset/-/bitset-5.2.3.tgz",
|
||||
"integrity": "sha512-uZ7++Z60MC9cZ+7YzQ1v9yPDydcjhmcMjGx2yoGTjjSXBoVMmTr2LCRbkpI19S9P/C75hhP7Bsakj+gVzVUDbQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/rawify"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
|
|
@ -1826,6 +1978,26 @@
|
|||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/blech32": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/blech32/-/blech32-1.1.2.tgz",
|
||||
"integrity": "sha512-C5qxzoF9KyX88X8Zz18cZ6BOeL0n5/Eg/cDot1frntkArRMwg1djNim5wA6QFWwu0lJ1LN8iiRMN4Lp2kZzdfA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"long": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/blech32/node_modules/long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/bn.js": {
|
||||
"version": "4.12.2",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
|
||||
|
|
@ -1871,6 +2043,42 @@
|
|||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/boltz-core": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boltz-core/-/boltz-core-3.0.0.tgz",
|
||||
"integrity": "sha512-L0jzUnTIb/vir9k6yVlCkV8I29ZeBK7LWq3rrDcp/KP7bB0VvKR5JTceua8g2KBCBM5HOMVDEuPW3c9/82/Nmg==",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@boltz/bitcoin-ops": "^2.0.0",
|
||||
"@openzeppelin/contracts": "^5.2.0",
|
||||
"@vulpemventures/secp256k1-zkp": "^3.2.1",
|
||||
"bip32": "^4.0.0",
|
||||
"bip65": "^1.0.3",
|
||||
"bip66": "^2.0.0",
|
||||
"bitcoinjs-lib": "^6.1.7",
|
||||
"bn.js": "^5.2.1",
|
||||
"ecpair": "^3.0.0",
|
||||
"varuint-bitcoin": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"liquidjs-lib": "^6.0.2-liquid.37"
|
||||
}
|
||||
},
|
||||
"node_modules/boltz-core/node_modules/bip66": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bip66/-/bip66-2.0.0.tgz",
|
||||
"integrity": "sha512-kBG+hSpgvZBrkIm9dt5T1Hd/7xGCPEX2npoxAWZfsK1FvjgaxySEh2WizjyIstWXriKo9K9uJ4u0OnsyLDUPXQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/boltz-core/node_modules/bn.js": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz",
|
||||
"integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
|
|
@ -1914,6 +2122,25 @@
|
|||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/bs58": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz",
|
||||
"integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base-x": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bs58check": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz",
|
||||
"integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.2.0",
|
||||
"bs58": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
|
|
@ -2204,7 +2431,6 @@
|
|||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz",
|
||||
"integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"safe-buffer": "^5.2.1"
|
||||
|
|
@ -2545,7 +2771,6 @@
|
|||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"cipher-base": "^1.0.1",
|
||||
"inherits": "^2.0.1",
|
||||
|
|
@ -2559,7 +2784,6 @@
|
|||
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"cipher-base": "^1.0.3",
|
||||
"create-hash": "^1.1.0",
|
||||
|
|
@ -2980,6 +3204,52 @@
|
|||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ecpair": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ecpair/-/ecpair-3.0.0.tgz",
|
||||
"integrity": "sha512-kf4JxjsRQoD4EBzpYjGAcR0t9i/4oAeRPtyCpKvSwyotgkc6oA4E4M0/e+kep7cXe+mgxAvoeh/jdgH9h5+Wxw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uint8array-tools": "^0.0.8",
|
||||
"valibot": "^0.37.0",
|
||||
"wif": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecpair/node_modules/uint8array-tools": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz",
|
||||
"integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecpair/node_modules/valibot": {
|
||||
"version": "0.37.0",
|
||||
"resolved": "https://registry.npmjs.org/valibot/-/valibot-0.37.0.tgz",
|
||||
"integrity": "sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ecpair/node_modules/wif": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wif/-/wif-5.0.0.tgz",
|
||||
"integrity": "sha512-iFzrC/9ne740qFbNjTZ2FciSRJlHIXoxqk/Y5EnE08QOXu1WjJyCCswwDTYbohAOEnlCtLaAAQBhyaLRFh2hMA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bs58check": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
|
|
@ -3775,7 +4045,6 @@
|
|||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
|
||||
"integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.6.0",
|
||||
|
|
@ -3790,7 +4059,6 @@
|
|||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
|
|
@ -3805,7 +4073,6 @@
|
|||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
|
|
@ -4332,6 +4599,88 @@
|
|||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/liquidjs-lib": {
|
||||
"version": "6.0.2-liquid.37",
|
||||
"resolved": "https://registry.npmjs.org/liquidjs-lib/-/liquidjs-lib-6.0.2-liquid.37.tgz",
|
||||
"integrity": "sha512-AOPwqg9wtLMNxfqOf8afC+bYYrs3VBsTq/Mq/iOe0F2X3CcbgiLeSAcvOY34jbnUre6U+zmuXKP9bWmxnOG08A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/randombytes": "^2.0.0",
|
||||
"bech32": "^2.0.0",
|
||||
"bip174-liquid": "^1.0.3",
|
||||
"bip66": "^1.1.0",
|
||||
"bitcoinjs-lib": "^6.0.2",
|
||||
"bitset": "^5.1.1",
|
||||
"blech32": "^1.0.1",
|
||||
"bs58check": "^2.0.0",
|
||||
"create-hash": "^1.2.0",
|
||||
"ecpair": "^2.1.0",
|
||||
"slip77": "^0.2.0",
|
||||
"typeforce": "^1.11.3",
|
||||
"varuint-bitcoin": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/liquidjs-lib/node_modules/base-x": {
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
|
||||
"integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/liquidjs-lib/node_modules/bs58": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
||||
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"base-x": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/liquidjs-lib/node_modules/bs58check": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
|
||||
"integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bs58": "^4.0.0",
|
||||
"create-hash": "^1.1.0",
|
||||
"safe-buffer": "^5.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/liquidjs-lib/node_modules/ecpair": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz",
|
||||
"integrity": "sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0",
|
||||
"typeforce": "^1.18.0",
|
||||
"wif": "^2.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/liquidjs-lib/node_modules/varuint-bitcoin": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz",
|
||||
"integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
|
|
@ -4512,7 +4861,6 @@
|
|||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
"integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
|
|
@ -5765,6 +6113,16 @@
|
|||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
|
|
@ -5981,7 +6339,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
|
||||
"integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1"
|
||||
|
|
@ -6382,6 +6739,28 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/slip77": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/slip77/-/slip77-0.2.0.tgz",
|
||||
"integrity": "sha512-LQaxb1Hef10kU36qvk71tlSt5BWph7GM0j+t2n5zs169X4QfnNbb6xqKZ38X3ETzGmCQaVdBwr925HDagHra/Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^13.9.1",
|
||||
"create-hmac": "^1.1.7",
|
||||
"typeforce": "^1.18.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/slip77/node_modules/@types/node": {
|
||||
"version": "13.13.52",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.52.tgz",
|
||||
"integrity": "sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
|
|
@ -6782,6 +7161,27 @@
|
|||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-secp256k1": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.4.tgz",
|
||||
"integrity": "sha512-FoDTcToPqZE454Q04hH9o2EhxWsm7pOSpicyHkgTwKhdKWdsTUuqfP5MLq3g+VjAtl2vSx6JpXGdwA2qpYkI0Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uint8array-tools": "0.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-secp256k1/node_modules/uint8array-tools": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz",
|
||||
"integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-buffer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
|
||||
|
|
@ -7003,6 +7403,12 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/typeforce": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
|
||||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/typeorm": {
|
||||
"version": "0.3.26",
|
||||
"resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.26.tgz",
|
||||
|
|
@ -7356,6 +7762,24 @@
|
|||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/varuint-bitcoin": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz",
|
||||
"integrity": "sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uint8array-tools": "^0.0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/varuint-bitcoin/node_modules/uint8array-tools": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz",
|
||||
"integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
|
@ -7458,6 +7882,44 @@
|
|||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"node_modules/wif": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz",
|
||||
"integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bs58check": "<3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wif/node_modules/base-x": {
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
|
||||
"integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/wif/node_modules/bs58": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
||||
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base-x": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/wif/node_modules/bs58check": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
|
||||
"integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bs58": "^4.0.0",
|
||||
"create-hash": "^1.1.0",
|
||||
"safe-buffer": "^5.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -36,10 +36,13 @@
|
|||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^17.0.31",
|
||||
"@types/secp256k1": "^4.0.3",
|
||||
"@vulpemventures/secp256k1-zkp": "^3.2.1",
|
||||
"axios": "^1.9.0",
|
||||
"bech32": "^2.0.0",
|
||||
"better-sqlite3": "^12.2.0",
|
||||
"bitcoin-core": "^4.2.0",
|
||||
"bitcoinjs-lib": "^6.1.7",
|
||||
"boltz-core": "^3.0.0",
|
||||
"chai": "^4.3.7",
|
||||
"chai-string": "^1.5.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
|
|
@ -47,6 +50,7 @@
|
|||
"csv": "^6.3.8",
|
||||
"dotenv": "^16.4.5",
|
||||
"eccrypto": "^1.1.6",
|
||||
"ecpair": "^3.0.0",
|
||||
"express": "^4.21.2",
|
||||
"globby": "^13.1.2",
|
||||
"grpc-tools": "^1.12.4",
|
||||
|
|
@ -58,6 +62,7 @@
|
|||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.5.5",
|
||||
"secp256k1": "^5.0.1",
|
||||
"tiny-secp256k1": "^2.2.4",
|
||||
"ts-node": "^10.7.0",
|
||||
"ts-proto": "^1.131.2",
|
||||
"typeorm": "^0.3.26",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { getLogger } from './services/helpers/logger.js';
|
|||
import { initMainHandler, initSettings } from './services/main/init.js';
|
||||
import { nip19 } from 'nostr-tools'
|
||||
import { LoadStorageSettingsFromEnv } from './services/storage/index.js';
|
||||
import Main from './services/main/index.js';
|
||||
//@ts-ignore
|
||||
const { nprofileEncode } = nip19
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ const start = async () => {
|
|||
adminManager.setAppNprofile(appNprofile)
|
||||
const Server = NewServer(serverMethods, serverOptions(mainHandler))
|
||||
Server.Listen(mainHandler.settings.getSettings().serviceSettings.servicePort)
|
||||
await TMP_swapTest_TMP(mainHandler) // TMP -- remove this
|
||||
}
|
||||
start()
|
||||
|
||||
|
|
@ -62,3 +64,9 @@ const exitHandler = async (kill: () => void) => {
|
|||
process.exit(99);
|
||||
});
|
||||
}
|
||||
|
||||
const TMP_swapTest_TMP = async (mainHandler: Main) => {
|
||||
const i = await mainHandler.lnd.NewInvoice(25000, 'test', 3600, { useProvider: false, from: 'user' })
|
||||
const decoded = await mainHandler.lnd.DecodeInvoice(i.payRequest)
|
||||
await mainHandler.paymentManager.swaps.SwapInvoice(i.payRequest, decoded.paymentHash)
|
||||
}
|
||||
341
src/services/lnd/swaps.ts
Normal file
341
src/services/lnd/swaps.ts
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
import zkpInit from '@vulpemventures/secp256k1-zkp';
|
||||
import axios from 'axios';
|
||||
import { crypto, initEccLib, Transaction, address, Network } from 'bitcoinjs-lib';
|
||||
// import bolt11 from 'bolt11';
|
||||
import {
|
||||
Musig, SwapTreeSerializer, TaprootUtils, detectSwap,
|
||||
constructClaimTransaction, targetFee, OutputType
|
||||
} from 'boltz-core';
|
||||
import { randomBytes, createHash } from 'crypto';
|
||||
import { ECPairFactory, ECPairInterface } from 'ecpair';
|
||||
import * as ecc from 'tiny-secp256k1';
|
||||
import ws from 'ws';
|
||||
import { getLogger, PubLogger, ERROR } from '../helpers/logger.js';
|
||||
import SettingsManager from '../main/settingsManager.js';
|
||||
|
||||
type InvoiceSwapResponse = { id: string, claimPublicKey: string, swapTree: string }
|
||||
type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface }
|
||||
type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo }
|
||||
|
||||
type TransactionSwapResponse = { id: string, refundPublicKey: string, swapTree: string }
|
||||
type TransactionSwapInfo = { destinationAddress: string, network: Network, preimage: Buffer, keys: ECPairInterface, txHex: string }
|
||||
type TransactionSwapData = { createdResponse: TransactionSwapResponse, info: TransactionSwapInfo }
|
||||
|
||||
export class Swaps {
|
||||
settings: SettingsManager
|
||||
log: PubLogger
|
||||
constructor(settings: SettingsManager) {
|
||||
this.settings = settings
|
||||
this.log = getLogger({ component: 'SwapsService' })
|
||||
initEccLib(ecc)
|
||||
}
|
||||
|
||||
SwapInvoice = async (invoice: string, paymentHash: string) => {
|
||||
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
||||
this.log(ERROR, 'Swaps are not enabled');
|
||||
return;
|
||||
}
|
||||
const keys = ECPairFactory(ecc).makeRandom()
|
||||
const refundPublicKey = Buffer.from(keys.publicKey).toString('hex')
|
||||
const req = { invoice, to: 'BTC', from: 'BTC', refundPublicKey }
|
||||
const url = `${this.settings.getSettings().swapsSettings.boltzHttpUrl}/v2/swap/submarine`
|
||||
this.log('Sending invoice swap request to', url);
|
||||
const createdResponse = await loggedPost<InvoiceSwapResponse>(this.log, url, req)
|
||||
if (!createdResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log('Created invoice swap');
|
||||
this.log(createdResponse);
|
||||
|
||||
const webSocket = new ws(`${this.settings.getSettings().swapsSettings.boltzWebSocketUrl}/v2/ws`)
|
||||
const subReq = { op: 'subscribe', channel: 'swap.update', args: [createdResponse.id] }
|
||||
webSocket.on('open', () => {
|
||||
webSocket.send(JSON.stringify(subReq))
|
||||
})
|
||||
|
||||
webSocket.on('message', async (rawMsg) => {
|
||||
try {
|
||||
await this.handleSwapInvoiceMessage(rawMsg, { createdResponse, info: { paymentHash, keys } }, () => webSocket.close())
|
||||
} catch (err: any) {
|
||||
this.log(ERROR, 'Error handling invoice WebSocket message', err.message)
|
||||
webSocket.close()
|
||||
return
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void) => {
|
||||
const msg = JSON.parse(rawMsg.toString('utf-8'));
|
||||
if (msg.event !== 'update') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log('Got invoice WebSocket update');
|
||||
this.log(msg);
|
||||
switch (msg.args[0].status) {
|
||||
// "invoice.set" means Boltz is waiting for an onchain transaction to be sent
|
||||
case 'invoice.set':
|
||||
this.log('Waiting for onchain transaction');
|
||||
return;
|
||||
// Create a partial signature to allow Boltz to do a key path spend to claim the mainchain coins
|
||||
case 'transaction.claim.pending':
|
||||
await this.handleInvoiceClaimPending(data)
|
||||
return;
|
||||
|
||||
case 'transaction.claimed':
|
||||
this.log('Invoice swap successful');
|
||||
closeWebSocket()
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleInvoiceClaimPending = async (data: InvoiceSwapData) => {
|
||||
this.log('Creating cooperative claim transaction');
|
||||
const { createdResponse, info } = data
|
||||
const { paymentHash, keys } = info
|
||||
const { boltzHttpUrl } = this.settings.getSettings().swapsSettings
|
||||
// Get the information request to create a partial signature
|
||||
const url = `${boltzHttpUrl}/v2/swap/submarine/${createdResponse.id}/claim`
|
||||
const claimTxDetails = await loggedGet<{ preimage: string, transactionHash: string, pubNonce: string }>(this.log, url)
|
||||
if (!claimTxDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that Boltz actually paid the invoice by comparing the preimage hash
|
||||
// of the invoice to the SHA256 hash of the preimage from the response
|
||||
const claimTxPreimageHash = createHash('sha256').update(Buffer.from(claimTxDetails.preimage, 'hex')).digest()
|
||||
const invoicePreimageHash = Buffer.from(paymentHash, 'hex')
|
||||
|
||||
if (!claimTxPreimageHash.equals(invoicePreimageHash)) {
|
||||
this.log(ERROR, 'Boltz provided invalid preimage');
|
||||
return;
|
||||
}
|
||||
|
||||
const boltzPublicKey = Buffer.from(createdResponse.claimPublicKey, 'hex')
|
||||
|
||||
// Create a musig signing instance
|
||||
const musig = new Musig(await zkpInit(), keys, randomBytes(32), [
|
||||
boltzPublicKey,
|
||||
Buffer.from(keys.publicKey),
|
||||
]);
|
||||
// Tweak that musig with the Taptree of the swap scripts
|
||||
TaprootUtils.tweakMusig(
|
||||
musig,
|
||||
SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree,
|
||||
);
|
||||
|
||||
// Aggregate the nonces
|
||||
musig.aggregateNonces([
|
||||
[boltzPublicKey, Buffer.from(claimTxDetails.pubNonce, 'hex')],
|
||||
]);
|
||||
// Initialize the session to sign the transaction hash from the response
|
||||
musig.initializeSession(
|
||||
Buffer.from(claimTxDetails.transactionHash, 'hex'),
|
||||
);
|
||||
|
||||
// Give our public nonce and the partial signature to Boltz
|
||||
const claimUrl = `${boltzHttpUrl}/v2/swap/submarine/${createdResponse.id}/claim`
|
||||
const claimReq = {
|
||||
pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'),
|
||||
partialSignature: Buffer.from(musig.signPartial()).toString('hex'),
|
||||
}
|
||||
const claimResponse = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq)
|
||||
if (!claimResponse) {
|
||||
return;
|
||||
}
|
||||
this.log('Claim response', claimResponse)
|
||||
}
|
||||
|
||||
SwapTransaction = async (destinationAddress: string, invoiceAmount: number, network: Network) => {
|
||||
if (!this.settings.getSettings().swapsSettings.enableSwaps) {
|
||||
this.log(ERROR, 'Swaps are not enabled');
|
||||
return;
|
||||
}
|
||||
const preimage = randomBytes(32);
|
||||
const keys = ECPairFactory(ecc).makeRandom()
|
||||
const url = `${this.settings.getSettings().swapsSettings.boltzHttpUrl}/v2/swap/reverse`
|
||||
const req = {
|
||||
invoiceAmount,
|
||||
to: 'BTC',
|
||||
from: 'BTC',
|
||||
claimPublicKey: Buffer.from(keys.publicKey).toString('hex'),
|
||||
preimageHash: createHash('sha256').update(preimage).digest('hex'),
|
||||
}
|
||||
const createdResponse = await loggedPost<TransactionSwapResponse>(this.log, url, req)
|
||||
if (!createdResponse) {
|
||||
return;
|
||||
}
|
||||
this.log('Created transaction swap');
|
||||
this.log(createdResponse);
|
||||
|
||||
const webSocket = new ws(`${this.settings.getSettings().swapsSettings.boltzWebSocketUrl}/v2/ws`)
|
||||
const subReq = { op: 'subscribe', channel: 'swap.update', args: [createdResponse.id] }
|
||||
webSocket.on('open', () => {
|
||||
webSocket.send(JSON.stringify(subReq))
|
||||
})
|
||||
|
||||
webSocket.on('message', async (rawMsg) => {
|
||||
try {
|
||||
await this.handleSwapTransactionMessage(rawMsg, { createdResponse, info: { destinationAddress, network, preimage, keys, txHex: '' } }, () => webSocket.close())
|
||||
} catch (err: any) {
|
||||
this.log(ERROR, 'Error handling transaction WebSocket message', err.message)
|
||||
webSocket.close()
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, closeWebSocket: () => void) => {
|
||||
const msg = JSON.parse(rawMsg.toString('utf-8'));
|
||||
if (msg.event !== 'update') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log('Got WebSocket update');
|
||||
this.log(msg);
|
||||
|
||||
switch (msg.args[0].status) {
|
||||
// "swap.created" means Boltz is waiting for the invoice to be paid
|
||||
case 'swap.created':
|
||||
this.log('Waiting invoice to be paid');
|
||||
return;
|
||||
|
||||
// "transaction.mempool" means that Boltz sent an onchain transaction
|
||||
case 'transaction.mempool':
|
||||
data.info.txHex = msg.args[0].transaction.hex
|
||||
await this.handleTransactionMempool(data)
|
||||
return
|
||||
case 'invoice.settled':
|
||||
this.log('Transaction swap successful');
|
||||
closeWebSocket()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleTransactionMempool = async (data: TransactionSwapData) => {
|
||||
this.log('Creating claim transaction');
|
||||
const { createdResponse, info } = data
|
||||
const { destinationAddress, network, keys, preimage, txHex } = info
|
||||
const boltzPublicKey = Buffer.from(
|
||||
createdResponse.refundPublicKey,
|
||||
'hex',
|
||||
);
|
||||
|
||||
// Create a musig signing session and tweak it with the Taptree of the swap scripts
|
||||
const musig = new Musig(await zkpInit(), keys, randomBytes(32), [
|
||||
boltzPublicKey,
|
||||
Buffer.from(keys.publicKey),
|
||||
]);
|
||||
const tweakedKey = TaprootUtils.tweakMusig(
|
||||
musig,
|
||||
SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree,
|
||||
);
|
||||
|
||||
// Parse the lockup transaction and find the output relevant for the swap
|
||||
const lockupTx = Transaction.fromHex(txHex);
|
||||
const swapOutput = detectSwap(tweakedKey, lockupTx);
|
||||
if (swapOutput === undefined) {
|
||||
this.log(ERROR, 'No swap output found in lockup transaction');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a claim transaction to be signed cooperatively via a key path spend
|
||||
const claimTx = targetFee(2, (fee) =>
|
||||
constructClaimTransaction(
|
||||
[
|
||||
{
|
||||
...swapOutput,
|
||||
keys,
|
||||
preimage,
|
||||
cooperative: true,
|
||||
type: OutputType.Taproot,
|
||||
txHash: lockupTx.getHash(),
|
||||
},
|
||||
],
|
||||
address.toOutputScript(destinationAddress, network),
|
||||
fee,
|
||||
),
|
||||
);
|
||||
const { boltzHttpUrl } = this.settings.getSettings().swapsSettings
|
||||
// Get the partial signature from Boltz
|
||||
const claimUrl = `${boltzHttpUrl}/v2/swap/reverse/${createdResponse.id}/claim`
|
||||
const claimReq = {
|
||||
index: 0,
|
||||
transaction: claimTx.toHex(),
|
||||
preimage: preimage.toString('hex'),
|
||||
pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'),
|
||||
}
|
||||
const boltzSig = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq)
|
||||
if (!boltzSig) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Aggregate the nonces
|
||||
musig.aggregateNonces([
|
||||
[boltzPublicKey, Buffer.from(boltzSig.pubNonce, 'hex')],
|
||||
]);
|
||||
|
||||
// Initialize the session to sign the claim transaction
|
||||
musig.initializeSession(
|
||||
claimTx.hashForWitnessV1(
|
||||
0,
|
||||
[swapOutput.script],
|
||||
[swapOutput.value],
|
||||
Transaction.SIGHASH_DEFAULT,
|
||||
),
|
||||
);
|
||||
|
||||
// Add the partial signature from Boltz
|
||||
musig.addPartial(
|
||||
boltzPublicKey,
|
||||
Buffer.from(boltzSig.partialSignature, 'hex'),
|
||||
);
|
||||
|
||||
// Create our partial signature
|
||||
musig.signPartial();
|
||||
|
||||
// Witness of the input to the aggregated signature
|
||||
claimTx.ins[0].witness = [musig.aggregatePartials()];
|
||||
|
||||
// Broadcast the finalized transaction
|
||||
const broadcastUrl = `${boltzHttpUrl}/v2/chain/BTC/transaction`
|
||||
const broadcastReq = {
|
||||
hex: claimTx.toHex(),
|
||||
}
|
||||
const broadcastResponse = await loggedPost(this.log, broadcastUrl, broadcastReq)
|
||||
if (!broadcastResponse) {
|
||||
return;
|
||||
}
|
||||
this.log('Transaction broadcasted', broadcastResponse)
|
||||
}
|
||||
}
|
||||
|
||||
const loggedPost = async <T>(log: PubLogger, url: string, req: any): Promise<T | null> => {
|
||||
try {
|
||||
const { data } = await axios.post(url, req)
|
||||
return data as T
|
||||
} catch (err: any) {
|
||||
if (err.response?.data) {
|
||||
log(ERROR, 'Error sending request', err.response.data)
|
||||
return null
|
||||
}
|
||||
log(ERROR, 'Error sending request', err.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const loggedGet = async <T>(log: PubLogger, url: string): Promise<T | null> => {
|
||||
try {
|
||||
const { data } = await axios.get(url)
|
||||
return data as T
|
||||
} catch (err: any) {
|
||||
if (err.response?.data) {
|
||||
log(ERROR, 'Error getting request', err.response.data)
|
||||
return null
|
||||
}
|
||||
log(ERROR, 'Error getting request', err.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import { LiquidityManager } from './liquidityManager.js'
|
|||
import { Utils } from '../helpers/utilsWrapper.js'
|
||||
import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js'
|
||||
import SettingsManager from './settingsManager.js'
|
||||
import { Swaps } from '../lnd/swaps.js'
|
||||
interface UserOperationInfo {
|
||||
serial_id: number
|
||||
paid_amount: number
|
||||
|
|
@ -51,6 +52,7 @@ export default class {
|
|||
watchDog: Watchdog
|
||||
liquidityManager: LiquidityManager
|
||||
utils: Utils
|
||||
swaps: Swaps
|
||||
constructor(storage: Storage, lnd: LND, settings: SettingsManager, liquidityManager: LiquidityManager, utils: Utils, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb) {
|
||||
this.storage = storage
|
||||
this.settings = settings
|
||||
|
|
@ -58,6 +60,7 @@ export default class {
|
|||
this.liquidityManager = liquidityManager
|
||||
this.utils = utils
|
||||
this.watchDog = new Watchdog(settings, this.liquidityManager, this.lnd, this.storage, this.utils, this.liquidityManager.rugPullTracker)
|
||||
this.swaps = new Swaps(settings)
|
||||
this.addressPaidCb = addressPaidCb
|
||||
this.invoicePaidCb = invoicePaidCb
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,22 @@ export const LoadLiquiditySettingsFromEnv = (dbEnv: Record<string, string | unde
|
|||
//const liquidityProviderPub = process.env.LIQUIDITY_PROVIDER_PUB === "null" ? "" : (process.env.LIQUIDITY_PROVIDER_PUB || "76ed45f00cea7bac59d8d0b7d204848f5319d7b96c140ffb6fcbaaab0a13d44e")
|
||||
const liquidityProviderPub = chooseEnv("LIQUIDITY_PROVIDER_PUB", dbEnv, "76ed45f00cea7bac59d8d0b7d204848f5319d7b96c140ffb6fcbaaab0a13d44e", addToDb)
|
||||
const disableLiquidityProvider = chooseEnvBool("DISABLE_LIQUIDITY_PROVIDER", dbEnv, false, addToDb) || liquidityProviderPub === "null"
|
||||
return { liquidityProviderPub, useOnlyLiquidityProvider: false, disableLiquidityProvider }
|
||||
const useOnlyLiquidityProvider = chooseEnvBool("USE_ONLY_LIQUIDITY_PROVIDER", dbEnv, false, addToDb)
|
||||
return { liquidityProviderPub, useOnlyLiquidityProvider, disableLiquidityProvider }
|
||||
}
|
||||
|
||||
export type SwapsSettings = {
|
||||
boltzHttpUrl: string
|
||||
boltzWebSocketUrl: string
|
||||
enableSwaps: boolean
|
||||
}
|
||||
|
||||
export const LoadSwapsSettingsFromEnv = (dbEnv: Record<string, string | undefined>, addToDb?: EnvCacher): SwapsSettings => {
|
||||
return {
|
||||
boltzHttpUrl: chooseEnv("BOLTZ_HTTP_URL", dbEnv, "http://127.0.0.1:9001", addToDb),
|
||||
boltzWebSocketUrl: chooseEnv("BOLTZ_WEBSOCKET_URL", dbEnv, "ws://127.0.0.1:9004", addToDb),
|
||||
enableSwaps: chooseEnvBool("ENABLE_SWAPS", dbEnv, false, addToDb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import {
|
|||
LiquiditySettings, LndNodeSettings, LndSettings, LoadLiquiditySettingsFromEnv,
|
||||
LoadLSPSettingsFromEnv, LSPSettings, ServiceFeeSettings, ServiceSettings, LoadServiceFeeSettingsFromEnv,
|
||||
LoadNostrRelaySettingsFromEnv, LoadServiceSettingsFromEnv, LoadWatchdogSettingsFromEnv,
|
||||
LoadLndNodeSettingsFromEnv, LoadLndSettingsFromEnv, NostrRelaySettings, WatchdogSettings
|
||||
LoadLndNodeSettingsFromEnv, LoadLndSettingsFromEnv, NostrRelaySettings, WatchdogSettings, SwapsSettings, LoadSwapsSettingsFromEnv
|
||||
|
||||
} from "./settings.js"
|
||||
export default class SettingsManager {
|
||||
storage: Storage
|
||||
|
|
@ -27,6 +28,7 @@ export default class SettingsManager {
|
|||
serviceFeeSettings: LoadServiceFeeSettingsFromEnv(dbEnv, addToDb),
|
||||
serviceSettings: LoadServiceSettingsFromEnv(dbEnv, addToDb),
|
||||
watchDogSettings: LoadWatchdogSettingsFromEnv(dbEnv, addToDb),
|
||||
swapsSettings: LoadSwapsSettingsFromEnv(dbEnv, addToDb),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,5 +150,6 @@ type FullSettings = {
|
|||
nostrRelaySettings: NostrRelaySettings,
|
||||
serviceFeeSettings: ServiceFeeSettings,
|
||||
serviceSettings: ServiceSettings,
|
||||
lspSettings: LSPSettings
|
||||
lspSettings: LSPSettings,
|
||||
swapsSettings: SwapsSettings
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue