diff --git a/packages/util-dev/src/mockProviders/mockData.ts b/packages/util-dev/src/mockProviders/mockData.ts index 3ae22a543af..c67cf47ce95 100644 --- a/packages/util-dev/src/mockProviders/mockData.ts +++ b/packages/util-dev/src/mockProviders/mockData.ts @@ -128,6 +128,51 @@ export const utxosWithLowCoins: Cardano.Utxo[] = [ ] ]; +export const impureUtxos: Cardano.Utxo[] = [ + [ + { + address: Cardano.PaymentAddress( + 'addr_test1qzs0umu0s2ammmpw0hea0w2crtcymdjvvlqngpgqy76gpfnuzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475qp3y3vz' + ), + index: 1, + txId: Cardano.TransactionId('c7c0973c6bbf1a04a9f306da7814b4fa564db649bf48b0bd93c273bd03143547') + }, + { + address: Cardano.PaymentAddress( + 'addr_test1qq585l3hyxgj3nas2v3xymd23vvartfhceme6gv98aaeg9muzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475q2g7k3g' + ), + value: { + assets: new Map([ + [AssetId.PXL, 5n], + [AssetId.TSLA, 10n] + ]), + coins: 4_027_026_465n + } + } + ], + [ + { + address: Cardano.PaymentAddress( + 'addr_test1qzs0umu0s2ammmpw0hea0w2crtcymdjvvlqngpgqy76gpfnuzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475qp3y3vz' + ), + index: 2, + txId: Cardano.TransactionId('c7c0973c6bbf1a04a9f306da7814b4fa564db649bf48b0bd93c273bd03143547') + }, + { + address: Cardano.PaymentAddress( + 'addr_test1qq585l3hyxgj3nas2v3xymd23vvartfhceme6gv98aaeg9muzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475q2g7k3g' + ), + value: { + assets: new Map([ + [AssetId.PXL, 5n], + [AssetId.TSLA, 10n] + ]), + coins: 4_027_026_465n + } + } + ] +]; + export const utxosWithLowCoinsAndMixedAssets: Cardano.Utxo[] = [ ...utxosWithLowCoins, [ diff --git a/packages/wallet/src/cip30.ts b/packages/wallet/src/cip30.ts index 035df752cea..016f63bd6e6 100644 --- a/packages/wallet/src/cip30.ts +++ b/packages/wallet/src/cip30.ts @@ -230,8 +230,8 @@ const getCollateralCallback = async ( callback: GetCollateralCallback, logger: Logger ) => { + if (availableUtxos.length === 0) return null; const availableUtxosWithoutAssets = getUtxosWithoutAssets(availableUtxos); - if (availableUtxosWithoutAssets.length === 0) return null; try { // Send the amount and filtered available UTxOs to the callback // Client can then choose to mark a UTxO set as unspendable diff --git a/packages/wallet/test/integration/cip30mapping.test.ts b/packages/wallet/test/integration/cip30mapping.test.ts index 1ba63c67c08..3eae979bebc 100644 --- a/packages/wallet/test/integration/cip30mapping.test.ts +++ b/packages/wallet/test/integration/cip30mapping.test.ts @@ -46,7 +46,8 @@ const { utxo: mockUtxo, utxosWithLowCoins, utxosWithLowCoinsAndMixedAssets, - sortedUtxosWithLowCoins + sortedUtxosWithLowCoins, + impureUtxos } = mocks; type TestProviders = Required>; @@ -269,6 +270,7 @@ describe('cip30', () => { }); }); + // eslint-disable-next-line max-statements describe('api.getCollateral', () => { // Wallet 2 let wallet2: BaseWallet; @@ -294,6 +296,14 @@ describe('cip30', () => { let wallet7: BaseWallet; let api7: WithSenderContext; + // Wallet 8 + let wallet8: BaseWallet; + let api8: WithSenderContext; + + // Wallet 9 + let wallet9: BaseWallet; + let api9: WithSenderContext; + beforeAll(async () => { // CREATE A WALLET WITH LOW COINS UTxOs ({ wallet: wallet2, api: api2 } = await createWalletAndApiWithStores(utxosWithLowCoins)); @@ -330,6 +340,24 @@ describe('cip30', () => { true, [] )); + + // WALLET WITH CALLBACK FOR GET COLLATERAL (BRAND NEW WALLET, NO UTXOS) + ({ wallet: wallet8, api: api8 } = await createWalletAndApiWithStores( + [], + providers, + mockCollateralCallback, + true, + [] + )); + + // WALLET WITH CALLBACK FOR GET COLLATERAL (ONLY IMPURE UTXOs) + ({ wallet: wallet9, api: api9 } = await createWalletAndApiWithStores( + [], + providers, + mockCollateralCallback, + true, + impureUtxos + )); }); afterAll(() => { @@ -387,6 +415,27 @@ describe('cip30', () => { wallet7.shutdown(); }); + it('does not execute collateral callback and returns null if brand new wallet (no UTXOS)', async () => { + await expect(api8.getCollateral(context)).resolves.toBeNull(); + expect(mockCollateralCallback).not.toHaveBeenCalled(); + wallet8.shutdown(); + }); + + it('does executes collateral callback with empty array if wallet has only impure UTXOS', async () => { + await expect(api9.getCollateral(context)).resolves.not.toBeNull(); + expect(mockCollateralCallback).toHaveBeenCalledWith({ + data: { + amount: 5_000_000n, + utxos: [] + }, + sender: { + url: 'https://lace.io' + }, + type: 'get_collateral' + }); + wallet9.shutdown(); + }); + it('does not execute collateral callback if not provided', async () => { await expect(api2.getCollateral(context)).rejects.toThrow(ApiError); expect(mockCollateralCallback).not.toHaveBeenCalled();