diff --git a/docker/build.py b/docker/build.py index a2acaf9d..554b2197 100755 --- a/docker/build.py +++ b/docker/build.py @@ -43,11 +43,11 @@ class Image: BITCOIN_VERSION = "26.0" LITECOIN_VERSION = "0.21.2.2" ELEMENTS_VERSION = "23.2.1" -GETH_VERSION = "1.13.10" +GETH_VERSION = "1.13.11" C_LIGHTNING_VERSION = "23.11.2" ECLAIR_VERSION = "0.9.0" -LND_VERSION = "0.17.3-beta" +LND_VERSION = "0.17.4-beta" BITCOIN_BUILD_ARG = BuildArgument( name="BITCOIN_VERSION", @@ -101,7 +101,7 @@ class Image: ], ), "regtest": Image( - tag="4.4.0", + tag="4.4.1", arguments=[ UBUNTU_VERSION, BITCOIN_BUILD_ARG, diff --git a/docker/regtest/startRegtest.sh b/docker/regtest/startRegtest.sh index b660ada2..f9c04a53 100755 --- a/docker/regtest/startRegtest.sh +++ b/docker/regtest/startRegtest.sh @@ -9,7 +9,7 @@ docker run \ --volume "${PWD}"/docker/regtest/data/cln/mpay:/root/.lightning/regtest/mpay \ --volume "${PWD}"/tools:/tools \ --network host \ - boltz/regtest:4.4.0 + boltz/regtest:4.4.1 docker exec regtest bash -c "cp /root/.lightning/regtest/*.pem /root/.lightning/regtest/certs" docker exec regtest chmod -R 777 /root/.lightning/regtest/certs diff --git a/lib/VersionCheck.ts b/lib/VersionCheck.ts index e20ad12e..2f3e7199 100644 --- a/lib/VersionCheck.ts +++ b/lib/VersionCheck.ts @@ -95,7 +95,7 @@ class VersionCheck { }, [LndClient.serviceName]: { minimal: '0.16.0', - maximal: '0.17.3', + maximal: '0.17.4', }, }; diff --git a/lib/api/Controller.ts b/lib/api/Controller.ts index 3dd90d00..6aa11024 100644 --- a/lib/api/Controller.ts +++ b/lib/api/Controller.ts @@ -474,7 +474,6 @@ class Controller { invoiceAmount, onchainAmount, claimPublicKey, - prepayMinerFee, } = validateRequest(req.body, [ { name: 'pairId', type: 'string' }, { name: 'orderSide', type: 'string' }, @@ -486,7 +485,6 @@ class Controller { { name: 'claimAddress', type: 'string', optional: true }, { name: 'invoiceAmount', type: 'number', optional: true }, { name: 'onchainAmount', type: 'number', optional: true }, - { name: 'prepayMinerFee', type: 'boolean', optional: true }, { name: 'claimPublicKey', type: 'string', hex: true, optional: true }, ]); @@ -503,7 +501,6 @@ class Controller { invoiceAmount, onchainAmount, claimPublicKey, - prepayMinerFee, userAddress: address, version: SwapVersion.Legacy, }); diff --git a/lib/api/v2/WebSocketHandler.ts b/lib/api/v2/WebSocketHandler.ts index 48915c75..2a3eea75 100644 --- a/lib/api/v2/WebSocketHandler.ts +++ b/lib/api/v2/WebSocketHandler.ts @@ -3,7 +3,6 @@ import ws from 'ws'; import { formatError } from '../../Utils'; import Service from '../../service/Service'; import Controller from '../Controller'; -import { apiPrefix } from './Consts'; enum Operation { // TODO: unsubscribe @@ -54,12 +53,6 @@ class WebSocketHandler { public register = (server: http.Server) => { server.on('upgrade', (request, socket, head) => { - if (request.url !== `${apiPrefix}/ws`) { - request.destroy(); - socket.destroy(); - return; - } - this.ws.handleUpgrade(request, socket, head, (ws) => { this.ws.emit('connection', ws, request); }); diff --git a/lib/api/v2/routers/SwapRouter.ts b/lib/api/v2/routers/SwapRouter.ts index b680ca25..3037cacf 100644 --- a/lib/api/v2/routers/SwapRouter.ts +++ b/lib/api/v2/routers/SwapRouter.ts @@ -649,8 +649,10 @@ class SwapRouter extends RouterBase { * description: SHA-256 hash of the preimage of the Reverse Swap encoded as HEX * claimPublicKey: * type: string - * required: true * description: Public key with which the Reverse Swap can be claimed encoded as HEX + * claimAddress: + * type: string + * description: EVM address with which the Reverse Swap can be claimed * invoiceAmount: * type: string * description: Amount for which the invoice should be; conflicts with "onchainAmount" @@ -909,8 +911,8 @@ class SwapRouter extends RouterBase { { name: 'from', type: 'string' }, { name: 'invoice', type: 'string', optional: true }, { name: 'pairHash', type: 'string', optional: true }, - { name: 'refundPublicKey', type: 'string', hex: true }, { name: 'referralId', type: 'string', optional: true }, + { name: 'refundPublicKey', type: 'string', hex: true, optional: true }, ]); const { pairId, orderSide } = this.service.convertToPairAndSide(from, to); @@ -1089,6 +1091,7 @@ class SwapRouter extends RouterBase { referralId, routingNode, preimageHash, + claimAddress, invoiceAmount, onchainAmount, claimPublicKey, @@ -1096,12 +1099,13 @@ class SwapRouter extends RouterBase { { name: 'to', type: 'string' }, { name: 'from', type: 'string' }, { name: 'preimageHash', type: 'string', hex: true }, - { name: 'claimPublicKey', type: 'string', hex: true }, { name: 'pairHash', type: 'string', optional: true }, { name: 'referralId', type: 'string', optional: true }, { name: 'routingNode', type: 'string', optional: true }, + { name: 'claimAddress', type: 'string', optional: true }, { name: 'invoiceAmount', type: 'number', optional: true }, { name: 'onchainAmount', type: 'number', optional: true }, + { name: 'claimPublicKey', type: 'string', hex: true, optional: true }, ]); checkPreimageHashLength(preimageHash); @@ -1114,6 +1118,7 @@ class SwapRouter extends RouterBase { referralId, routingNode, preimageHash, + claimAddress, invoiceAmount, onchainAmount, claimPublicKey, diff --git a/lib/rates/providers/RateProviderTaproot.ts b/lib/rates/providers/RateProviderTaproot.ts index c84a11ce..9a4128f3 100644 --- a/lib/rates/providers/RateProviderTaproot.ts +++ b/lib/rates/providers/RateProviderTaproot.ts @@ -299,7 +299,7 @@ class RateProviderTaproot extends RateProviderBase { return false; } - return cur.chainClient !== undefined; + return cur.chainClient !== undefined || cur.provider !== undefined; }; } diff --git a/lib/service/Service.ts b/lib/service/Service.ts index 227c6c5b..c150f8da 100644 --- a/lib/service/Service.ts +++ b/lib/service/Service.ts @@ -872,6 +872,10 @@ class Service { } break; + case CurrencyType.Ether: + case CurrencyType.ERC20: + break; + default: if (args.version !== SwapVersion.Legacy) { throw Errors.UNSUPPORTED_SWAP_VERSION(); diff --git a/lib/service/cooperative/EipSigner.ts b/lib/service/cooperative/EipSigner.ts index a9d9f4e2..e8da21aa 100644 --- a/lib/service/cooperative/EipSigner.ts +++ b/lib/service/cooperative/EipSigner.ts @@ -28,6 +28,14 @@ class EipSigner { } const { base, quote } = splitPairId(swap.pair); + const chainSymbol = getChainCurrency(base, quote, swap.orderSide, false); + const manager = this.walletManager.ethereumManagers.find((man) => + man.hasSymbol(chainSymbol), + ); + + if (manager === undefined) { + throw 'chain currency is not EVM based'; + } if ( !(await MusigSigner.isEligibleForRefund( @@ -47,15 +55,6 @@ class EipSigner { `Creating EIP-712 signature for refund of Swap ${swap.id}`, ); - const chainSymbol = getChainCurrency(base, quote, swap.orderSide, false); - const manager = this.walletManager.ethereumManagers.find((man) => - man.hasSymbol(chainSymbol), - ); - - if (manager === undefined) { - throw 'no signer for currency'; - } - const { domain, types, value } = await this.getSigningData( manager, chainSymbol, diff --git a/lib/service/cooperative/MusigSigner.ts b/lib/service/cooperative/MusigSigner.ts index bf0ab110..472ddcff 100644 --- a/lib/service/cooperative/MusigSigner.ts +++ b/lib/service/cooperative/MusigSigner.ts @@ -54,6 +54,13 @@ class MusigSigner { } const { base, quote } = splitPairId(swap.pair); + const currency = this.currencies.get( + getChainCurrency(base, quote, swap.orderSide, false), + )!; + + if (currency.chainClient === undefined) { + throw 'chain currency is not UTXO based'; + } if ( swap.version !== SwapVersion.Taproot || @@ -74,9 +81,6 @@ class MusigSigner { `Creating partial signature for refund of Swap ${swap.id}`, ); - const currency = this.currencies.get( - getChainCurrency(base, quote, swap.orderSide, false), - )!; const swapTree = SwapTreeSerializer.deserializeSwapTree(swap.redeemScript!); return this.createPartialSignature( diff --git a/lib/swap/SwapManager.ts b/lib/swap/SwapManager.ts index be1c2d75..f7e2367a 100644 --- a/lib/swap/SwapManager.ts +++ b/lib/swap/SwapManager.ts @@ -365,10 +365,10 @@ class SwapManager { id, pair, - lockupAddress: result.address, + version: args.version, referral: args.referralId, orderSide: args.orderSide, - version: SwapVersion.Legacy, + lockupAddress: result.address, status: SwapUpdateEvent.SwapCreated, preimageHash: getHexString(args.preimageHash), timeoutBlockHeight: result.timeoutBlockHeight, diff --git a/swagger-spec.json b/swagger-spec.json index df1a4bb7..7d3fedd6 100644 --- a/swagger-spec.json +++ b/swagger-spec.json @@ -1719,9 +1719,12 @@ }, "claimPublicKey": { "type": "string", - "required": true, "description": "Public key with which the Reverse Swap can be claimed encoded as HEX" }, + "claimAddress": { + "type": "string", + "description": "EVM address with which the Reverse Swap can be claimed" + }, "invoiceAmount": { "type": "string", "description": "Amount for which the invoice should be; conflicts with \"onchainAmount\"" diff --git a/test/integration/service/cooperative/EipSigner.spec.ts b/test/integration/service/cooperative/EipSigner.spec.ts index bc1b0e4e..d7433094 100644 --- a/test/integration/service/cooperative/EipSigner.spec.ts +++ b/test/integration/service/cooperative/EipSigner.spec.ts @@ -114,7 +114,7 @@ describe('EipSigner', () => { status: SwapUpdateEvent.InvoiceFailedToPay, }); await expect(signer.signSwapRefund('no signer')).rejects.toEqual( - 'no signer for currency', + 'chain currency is not EVM based', ); }); diff --git a/test/integration/service/cooperative/MusigSigner.spec.ts b/test/integration/service/cooperative/MusigSigner.spec.ts index c8bfeeb5..d37c3c85 100644 --- a/test/integration/service/cooperative/MusigSigner.spec.ts +++ b/test/integration/service/cooperative/MusigSigner.spec.ts @@ -69,7 +69,10 @@ describe('MusigSigner', () => { const signer = new MusigSigner( Logger.disabledLogger, - new Map([['BTC', btcCurrency]]), + new Map([ + ['BTC', btcCurrency], + ['noChainClient', {}], + ]), walletManager, nursery, ); @@ -179,6 +182,18 @@ describe('MusigSigner', () => { await bitcoinClient.sendRawTransaction(refundTx.toHex()); }); + test('should throw when creating refund signature for onchain currency that is not UTXO based', async () => { + SwapRepository.getSwap = jest.fn().mockResolvedValue({ + pair: 'noChainClient/BTC', + side: OrderSide.BUY, + }); + + const id = 'noChain'; + await expect( + signer.signSwapRefund(id, Buffer.alloc(0), Buffer.alloc(0), 0), + ).rejects.toEqual('chain currency is not UTXO based'); + }); + test('should throw when creating refund signature for swap that does not exist', async () => { SwapRepository.getSwap = jest.fn().mockResolvedValue(undefined); diff --git a/test/unit/api/Controller.spec.ts b/test/unit/api/Controller.spec.ts index a9a5057f..c2e7868e 100644 --- a/test/unit/api/Controller.spec.ts +++ b/test/unit/api/Controller.spec.ts @@ -985,32 +985,13 @@ describe('Controller', () => { requestData.pairHash = undefined; - // Should parse and pass the prepay miner fee boolean - requestData.prepayMinerFee = true; - - await controller.createSwap(mockRequest(requestData), res); - - expect(service.createReverseSwap).toHaveBeenNthCalledWith(5, { - prepayMinerFee: true, - pairId: requestData.pairId, - version: SwapVersion.Legacy, - orderSide: requestData.orderSide, - invoiceAmount: requestData.invoiceAmount, - preimageHash: getHexBuffer(requestData.preimageHash), - claimPublicKey: getHexBuffer(requestData.claimPublicKey), - }); - - expect(res.status).toHaveBeenNthCalledWith(4, 201); - expect(res.json).toHaveBeenNthCalledWith(4, await mockCreateReverseSwap()); - // Should parse and pass onchain amount requestData.onchainAmount = 123; requestData.invoiceAmount = undefined; await controller.createSwap(mockRequest(requestData), res); - expect(service.createReverseSwap).toHaveBeenNthCalledWith(7, { - prepayMinerFee: true, + expect(service.createReverseSwap).toHaveBeenNthCalledWith(5, { pairId: requestData.pairId, version: SwapVersion.Legacy, orderSide: requestData.orderSide, @@ -1019,16 +1000,15 @@ describe('Controller', () => { claimPublicKey: getHexBuffer(requestData.claimPublicKey), }); - expect(res.status).toHaveBeenNthCalledWith(5, 201); - expect(res.json).toHaveBeenNthCalledWith(5, await mockCreateReverseSwap()); + expect(res.status).toHaveBeenNthCalledWith(4, 201); + expect(res.json).toHaveBeenNthCalledWith(4, await mockCreateReverseSwap()); // Should parse and pass referral IDs requestData.referralId = 'someId'; await controller.createSwap(mockRequest(requestData), res); - expect(service.createReverseSwap).toHaveBeenNthCalledWith(9, { - prepayMinerFee: true, + expect(service.createReverseSwap).toHaveBeenNthCalledWith(7, { pairId: requestData.pairId, version: SwapVersion.Legacy, orderSide: requestData.orderSide, @@ -1038,8 +1018,8 @@ describe('Controller', () => { claimPublicKey: getHexBuffer(requestData.claimPublicKey), }); - expect(res.status).toHaveBeenNthCalledWith(6, 201); - expect(res.json).toHaveBeenNthCalledWith(6, await mockCreateReverseSwap()); + expect(res.status).toHaveBeenNthCalledWith(5, 201); + expect(res.json).toHaveBeenNthCalledWith(5, await mockCreateReverseSwap()); }); test('should query referrals', async () => { diff --git a/test/unit/api/v2/routers/SwapRouter.spec.ts b/test/unit/api/v2/routers/SwapRouter.spec.ts index 7b550531..8daa4cfa 100644 --- a/test/unit/api/v2/routers/SwapRouter.spec.ts +++ b/test/unit/api/v2/routers/SwapRouter.spec.ts @@ -248,7 +248,6 @@ describe('SwapRouter', () => { error | body ${'undefined parameter: to'} | ${{}} ${'undefined parameter: from'} | ${{ to: 'BTC' }} - ${'undefined parameter: refundPublicKey'} | ${{ to: 'BTC', from: 'L-BTC', invoice: 'lnbc1' }} ${'could not parse hex string: refundPublicKey'} | ${{ to: 'BTC', from: 'L-BTC', invoice: 'lnbc1', refundPublicKey: 'notHex' }} `( 'should not create submarine swaps with invalid parameters ($error)', @@ -673,7 +672,6 @@ describe('SwapRouter', () => { ${'undefined parameter: from'} | ${{ to: 'L-BTC' }} ${'undefined parameter: preimageHash'} | ${{ to: 'L-BTC', from: 'BTC' }} ${'could not parse hex string: preimageHash'} | ${{ to: 'L-BTC', from: 'BTC', preimageHash: 'notHex' }} - ${'undefined parameter: claimPublicKey'} | ${{ to: 'L-BTC', from: 'BTC', preimageHash: '00' }} ${'could not parse hex string: claimPublicKey'} | ${{ to: 'L-BTC', from: 'BTC', preimageHash: '00', claimPublicKey: 'notHex' }} ${'could not parse hex string: claimPublicKey'} | ${{ to: 'L-BTC', from: 'BTC', preimageHash: '00', claimPublicKey: 'notHex' }} `( diff --git a/test/unit/rates/providers/RateProviderTaproot.spec.ts b/test/unit/rates/providers/RateProviderTaproot.spec.ts index e47c882f..dbdf73aa 100644 --- a/test/unit/rates/providers/RateProviderTaproot.spec.ts +++ b/test/unit/rates/providers/RateProviderTaproot.spec.ts @@ -395,7 +395,7 @@ describe('RateProviderTaproot', () => { currency | expected ${'BTC'} | ${true} ${'L-BTC'} | ${true} - ${'R-BTC'} | ${false} + ${'R-BTC'} | ${true} ${'CASHU'} | ${false} `( 'should check if $currency can be used onchain',