diff --git a/.changeset/lucky-beans-retire.md b/.changeset/lucky-beans-retire.md new file mode 100644 index 00000000..28a7b48f --- /dev/null +++ b/.changeset/lucky-beans-retire.md @@ -0,0 +1,5 @@ +--- +'ptokens-dapp-v2': minor +--- + +add AGA, BORG, ETH and USDT on Ultra diff --git a/__mocks__/@p.network/ptokens-node.js b/__mocks__/@p.network/ptokens-node.js index f3bde11a..b223a31e 100644 --- a/__mocks__/@p.network/ptokens-node.js +++ b/__mocks__/@p.network/ptokens-node.js @@ -256,6 +256,261 @@ const supported = { }, }, ], + aga: [ + { + chainId: '0x005fe7f9', + isNative: true, + vaultAddress: 'e396757ec7e6ac7c8e5abe7285dde47b98f22db8', + identity: '341aa660fd5c280f5a9501e3822bb4a98e816d1b', + tokenReference: '0x8fea8ad36166ad36ca4f671b1af6307eebb7a9a8', + tokenAddress: '0x87b46212e805a3998b7e8077e9019c90759ea88c', + tokenDecimals: 18, + fees: { + networkFee: 0, + networkFeeUsd: 20, + basisPoints: { + nativeToHost: 0, + nativeToNative: 0, + }, + minNodeOperatorFee: 0, + minNodeOperatorFeeUsd: 0, + }, + }, + { + chainId: '0x02f9337d', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: '8fea8ad36166ad36ca4f671b1af6307eebb7a9a8', + tokenAddress: 'aga.ptokens', + tokenDecimals: 9, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 0, + hostToNative: 0, + }, + minNodeOperatorFee: 0, + minNodeOperatorFeeUsd: 0, + }, + }, + ], + borg: [ + { + chainId: '0x005fe7f9', + isNative: true, + vaultAddress: 'e396757ec7e6ac7c8e5abe7285dde47b98f22db8', + identity: '341aa660fd5c280f5a9501e3822bb4a98e816d1b', + tokenReference: '0xbe8bc8841fd4028f9350d69b8ba41e67b0ed8ec7', + tokenAddress: '0x64d0f55cd8c7133a9d7102b13987235f486f2224', + tokenDecimals: 18, + fees: { + networkFee: 0, + networkFeeUsd: 20, + basisPoints: { + nativeToHost: 0, + nativeToNative: 0, + }, + minNodeOperatorFee: 0, + minNodeOperatorFeeUsd: 0, + }, + }, + { + chainId: '0x02f9337d', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: 'be8bc8841fd4028f9350d69b8ba41e67b0ed8ec7', + tokenAddress: 'borg.ptokens', + tokenDecimals: 9, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 0, + hostToNative: 0, + }, + minNodeOperatorFee: 0, + minNodeOperatorFeeUsd: 0, + }, + }, + ], + usdt: [ + { + chainId: '0x03c38e67', + isNative: false, + vaultAddress: null, + identity: 'XXMOLMZYB5SMKNZP4PN4FRR5EX64BJURDZDYSQULMXS5SB354SDLBZX6HI', + tokenReference: '0xfefa7044416b10b2b1458bec31f3aea1ada41398', + tokenAddress: '748208047', + tokenDecimals: 6, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 10000000000000000000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x028c7109', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: 'fefa7044416b10b2b1458bec31f3aea1ada41398', + tokenAddress: 'usdt.ptokens', + tokenDecimals: 6, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 10000000000000000000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x026776fa', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: '0xfefa7044416b10b2b1458bec31f3aea1ada41398', + tokenAddress: 'usdt.ptokens', + tokenDecimals: 9, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 10000000000000000000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x005fe7f9', + isNative: true, + vaultAddress: 'e396757ec7e6ac7c8e5abe7285dde47b98f22db8', + identity: '341aa660fd5c280f5a9501e3822bb4a98e816d1b', + tokenReference: '0xfefa7044416b10b2b1458bec31f3aea1ada41398', + tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7', + tokenDecimals: 6, + fees: { + networkFee: 20000000000000000000, + networkFeeUsd: 20, + basisPoints: { + nativeToHost: 10, + nativeToNative: 25, + }, + minNodeOperatorFee: 10000000000000000000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x02f9337d', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: 'fefa7044416b10b2b1458bec31f3aea1ada41398', + tokenAddress: 'usdt.ptokens', + tokenDecimals: 6, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 10000000000000000000, + minNodeOperatorFeeUsd: 10, + }, + }, + ], + eth: [ + { + chainId: '0x005fe7f9', + isNative: true, + vaultAddress: 'e396757ec7e6ac7c8e5abe7285dde47b98f22db8', + identity: '341aa660fd5c280f5a9501e3822bb4a98e816d1b', + tokenReference: '0xbc6f2df529fcda4856f4d311c8c5307563c16654', + tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + tokenDecimals: 18, + fees: { + networkFee: 6939625260234000, + networkFeeUsd: 20, + basisPoints: { + nativeToHost: 10, + nativeToNative: 25, + }, + minNodeOperatorFee: 3469812630117000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x02e7261c', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: 'bc6f2df529fcda4856f4d311c8c5307563c16654', + tokenAddress: 'eth.ptokens', + tokenDecimals: 9, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 3469812630117000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x028c7109', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: 'bc6f2df529fcda4856f4d311c8c5307563c16654', + tokenAddress: 'eth.ptokens', + tokenDecimals: 9, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 3469812630117000, + minNodeOperatorFeeUsd: 10, + }, + }, + { + chainId: '0x02f9337d', + isNative: false, + vaultAddress: null, + identity: 'Not set!', + tokenReference: 'bc6f2df529fcda4856f4d311c8c5307563c16654', + tokenAddress: 'eth.ptokens', + tokenDecimals: 9, + fees: { + networkFee: 0, + networkFeeUsd: 0, + basisPoints: { + hostToHost: 10, + hostToNative: 25, + }, + minNodeOperatorFee: 3469812630117000, + minNodeOperatorFeeUsd: 10, + }, + }, + ], } export { pTokensNode } from '@p.network/ptokens-node' @@ -273,6 +528,14 @@ export class pTokensNodeProvider { return Promise.resolve(supported.zmt) } else if (_params[0].toLowerCase().endsWith('usdc')) { return Promise.resolve(supported.usdc) + } else if (_params[0].toLowerCase().endsWith('aga')) { + return Promise.resolve(supported.aga) + } else if (_params[0].toLowerCase().endsWith('borg')) { + return Promise.resolve(supported.borg) + } else if (_params[0].toLowerCase().endsWith('usdt')) { + return Promise.resolve(supported.usdt) + } else if (_params[0].toLowerCase().endsWith('eth')) { + return Promise.resolve(supported.eth) } } } diff --git a/public/assets/svg/AGA.svg b/public/assets/svg/AGA.svg new file mode 100644 index 00000000..dfb1f7a1 --- /dev/null +++ b/public/assets/svg/AGA.svg @@ -0,0 +1,82 @@ + + + + + \ No newline at end of file diff --git a/public/assets/svg/BORG.svg b/public/assets/svg/BORG.svg new file mode 100644 index 00000000..c7b2727b --- /dev/null +++ b/public/assets/svg/BORG.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/settings/swap-assets.js b/src/settings/swap-assets.js index c7b0df12..7309e29a 100644 --- a/src/settings/swap-assets.js +++ b/src/settings/swap-assets.js @@ -365,6 +365,29 @@ const swapAssets = [ chainId: ChainId.TelosMainnet, onPnetworkV2: true, }, + { + address: 'eosio.token', + id: 'PETH_ON_ULTRA_MAINNET', + name: 'pETH', + workingName: 'peth', + nativeDecimals: 18, + network: 'mainnet', + isHidden: false, + blockchain: 'ULTRA', + decimals: 9, + withMiniImage: true, + symbol: 'PETH', + isPtoken: true, + isPerc20: true, + nativeSymbol: 'ETH', + nativeBlockchain: 'ETH', + image: 'ETH.svg', + withBalanceDecimalsConversion: false, + chainId: ChainId.UltraMainnet, + onPnetworkV2: true, + symbolToDisplay: 'ETH', + symbolBalance: 'ETH', + }, { address: 'usdt.ptokens', id: 'PUSDT_ON_TELOS_MAINNET', @@ -407,6 +430,29 @@ const swapAssets = [ chainId: ChainId.LibreMainnet, onPnetworkV2: true, }, + { + address: 'eosio.token', + id: 'PUSDT_ON_ULTRA_MAINNET', + name: 'pUSDT', + workingName: 'pusdt', + nativeDecimals: 6, + network: 'mainnet', + isHidden: false, + blockchain: 'ULTRA', + decimals: 6, + withMiniImage: true, + symbol: 'PUSDT', + isPtoken: true, + nativeSymbol: 'USDT', + nativeBlockchain: 'ETH', + image: 'USDT.svg', + withBalanceDecimalsConversion: false, + isPerc20: true, + chainId: ChainId.UltraMainnet, + onPnetworkV2: true, + symbolToDisplay: 'USDT', + symbolBalance: 'USDT', + }, { address: 'usdc.ptokens', id: 'PUSDC_ON_TELOS_MAINNET', @@ -1039,6 +1085,52 @@ const swapAssets = [ withBalanceDecimalsConversion: true, chainId: ChainId.XdaiMainnet, }, + { + address: 'eosio.token', + id: 'PAGA_ON_ULTRA_MAINNET', + name: 'pAGA', + workingName: 'paga', + nativeDecimals: 18, + network: 'mainnet', + isHidden: false, + blockchain: 'ULTRA', + decimals: 9, + withMiniImage: true, + symbol: 'PAGA', + isPtoken: true, + nativeSymbol: 'AGA', + nativeBlockchain: 'ETH', + image: 'AGA.svg', + withBalanceDecimalsConversion: false, + isPerc20: true, + chainId: ChainId.UltraMainnet, + onPnetworkV2: true, + symbolToDisplay: 'AGA', + symbolBalance: 'AGA', + }, + { + address: 'eosio.token', + id: 'PBORG_ON_ULTRA_MAINNET', + name: 'pBORG', + workingName: 'pborg', + nativeDecimals: 18, + network: 'mainnet', + isHidden: false, + blockchain: 'ULTRA', + decimals: 9, + withMiniImage: true, + symbol: 'PBORG', + isPtoken: true, + nativeSymbol: 'BORG', + nativeBlockchain: 'ETH', + image: 'BORG.svg', + withBalanceDecimalsConversion: false, + isPerc20: true, + chainId: ChainId.UltraMainnet, + onPnetworkV2: true, + symbolToDisplay: 'BORG', + symbolBalance: 'BORG', + }, /* ################# Native Tokens #################*/ { address: '0x0000000000000000000000000000000000000000', @@ -1481,6 +1573,38 @@ const swapAssets = [ withBalanceDecimalsConversion: true, chainId: ChainId.EthereumMainnet, }, + { + address: '0x87B46212e805A3998B7e8077E9019c90759Ea88C', + id: 'AGA', + symbol: 'AGA', + name: 'Agora DEX Token', + network: 'mainnet', + blockchain: 'ETH', + decimals: 18, + withMiniImage: true, + isNative: true, + nativeSymbol: 'AGA', + nativeBlockchain: 'ETH', + image: 'AGA.svg', + withBalanceDecimalsConversion: true, + chainId: ChainId.EthereumMainnet, + }, + { + address: '0x64d0f55Cd8C7133a9D7102b13987235F486F2224', + id: 'BORG', + symbol: 'BORG', + name: 'SwissBorg Token', + network: 'mainnet', + blockchain: 'ETH', + decimals: 18, + withMiniImage: true, + isNative: true, + nativeSymbol: 'BORG', + nativeBlockchain: 'ETH', + image: 'BORG.svg', + withBalanceDecimalsConversion: true, + chainId: ChainId.EthereumMainnet, + }, ] export default swapAssets diff --git a/src/store/swap/__tests__/swap.actions.test.js b/src/store/swap/__tests__/swap.actions.test.js index 1703797f..52482808 100644 --- a/src/store/swap/__tests__/swap.actions.test.js +++ b/src/store/swap/__tests__/swap.actions.test.js @@ -78,14 +78,20 @@ describe('swap', () => { }) }) - it('Should peg-out pUOS on Ultra', async () => { + test.each([ + ['PUOS_ON_ULTRA_MAINNET', 'UOS', '100.00000000 UOS'], + ['PAGA_ON_ULTRA_MAINNET', 'AGA', '100.000000000 AGA'], + ['PBORG_ON_ULTRA_MAINNET', 'BORG', '100.000000000 BORG'], + ['PUSDT_ON_ULTRA_MAINNET', 'USDT', '100.000000 USDT'], + ['PETH_ON_ULTRA_MAINNET', 'ETH', '100.000000000 ETH'], + ])('Should peg-out %s on Ultra', async (_from, _to, _quantity, _setAmount) => { vi.spyOn(wallets, 'getWallets').mockReturnValue({ ultra: { provider: undefined, account: 'sender' }, eth: {} }) const pegoutSpy = vi.spyOn(pegout, 'default').mockResolvedValue() const addDestinationAssetSpy = vi.spyOn(pTokensSwapBuilder.prototype, 'addDestinationAsset') const setAmountSpy = vi.spyOn(pTokensSwapBuilder.prototype, 'setAmount') const setCustomActionsSpy = vi.spyOn(pTokensEosioAsset.prototype, 'setCustomActions') - const from = assets.find((_el) => _el.id === 'PUOS_ON_ULTRA_MAINNET') - const to = assets.find((_el) => _el.id === 'UOS') + const from = assets.find((_el) => _el.id === _from) + const to = assets.find((_el) => _el.id === _to) const amount = '100' const address = '0xF39d30Fa570db7940e5b3A3e42694665A1449E4B' const f = swap(from, to, amount, address) @@ -100,7 +106,7 @@ describe('swap', () => { arguments: { from: 'sender', memo: '0xF39d30Fa570db7940e5b3A3e42694665A1449E4B', - quantity: '100.00000000 UOS', + quantity: _quantity, to: 'ultra.swap', }, contractAddress: 'eosio.token', @@ -150,6 +156,41 @@ describe('swap', () => { }) }) + test.each([ + ['ETH', 'PETH_ON_ULTRA_MAINNET'], + ['AGA', 'PAGA_ON_ULTRA_MAINNET'], + ['BORG', 'PBORG_ON_ULTRA_MAINNET'], + ['USDT', 'PUSDT_ON_ULTRA_MAINNET'], + ['UOS', 'PUOS_ON_ULTRA_MAINNET'], + ])('Should peg-in % to Ultra', async (_from, _to) => { + const peginWithWalletSpy = vi.spyOn(peginWithWallet, 'default').mockResolvedValue() + const addDestinationAssetSpy = vi.spyOn(pTokensSwapBuilder.prototype, 'addDestinationAsset') + const setAmountSpy = vi.spyOn(pTokensSwapBuilder.prototype, 'setAmount') + const from = assets.find((_el) => _el.id === _from) + const to = assets.find((_el) => _el.id === _to) + const amount = '1000' + const address = 'pnettestacnt' + const f = swap(from, to, amount, address) + const dispatch = vi.fn() + await f(dispatch) + expect(setAmountSpy).toHaveBeenCalledTimes(1) + expect(setAmountSpy).toHaveBeenNthCalledWith(1, '1000') + expect(addDestinationAssetSpy).toHaveBeenCalledTimes(1) + expect(addDestinationAssetSpy).toHaveBeenNthCalledWith( + 1, + expect.anything(), + 'ultra.swap', + '0x706e65747465737461636e74' + ) + expect(peginWithWalletSpy).toHaveBeenCalledTimes(1) + expect(peginWithWalletSpy).toHaveBeenNthCalledWith(1, { + swap: expect.any(pTokensSwap), + ptokenFrom: from, + ptokenTo: to, + dispatch, + }) + }) + it('Should peg-out pBTC on Algorand', async () => { const pegoutSpy = vi.spyOn(pegout, 'default').mockResolvedValue() const addDestinationAssetSpy = vi.spyOn(pTokensSwapBuilder.prototype, 'addDestinationAsset') diff --git a/src/store/swap/swap.actions.js b/src/store/swap/swap.actions.js index 5e607122..ef3a5378 100644 --- a/src/store/swap/swap.actions.js +++ b/src/store/swap/swap.actions.js @@ -351,7 +351,13 @@ const swap = (_from, _to, _amount, _address, _opts = {}) => { swapInfo, }) sourceAsset.setCustomTransactions(txs) - } else if (_from.id === 'PUOS_ON_ULTRA_MAINNET') { + } else if ( + _from.id === 'PUOS_ON_ULTRA_MAINNET' || + _from.id === 'PUSDT_ON_ULTRA_MAINNET' || + _from.id === 'PETH_ON_ULTRA_MAINNET' || + _from.id === 'PBORG_ON_ULTRA_MAINNET' || + _from.id === 'PAGA_ON_ULTRA_MAINNET' + ) { const actions = [ { contractAddress: 'eosio.token', @@ -361,7 +367,7 @@ const swap = (_from, _to, _amount, _address, _opts = {}) => { from: wallets[_from.blockchain.toLowerCase()].account, to: 'ultra.swap', // it is UOS we need to transfer to ultra.swap, not PUOS - quantity: getAmountInEosFormat(_amount, _from.decimals, 'UOS'), + quantity: getAmountInEosFormat(_amount, _from.decimals, _from.symbolBalance), memo: _address, }, }, @@ -382,7 +388,13 @@ const swap = (_from, _to, _amount, _address, _opts = {}) => { encodeUserData(_address, parseInt(input_asset_id, 10), _amount, parseInt(output_asset_id, 10), 0) ) swapBuilder.addDestinationAsset(destinationAsset, _to.swapperAddress, metadata) - } else if (_to.id === 'PUOS_ON_ULTRA_MAINNET') { + } else if ( + _to.id === 'PUOS_ON_ULTRA_MAINNET' || + _to.id === 'PUSDT_ON_ULTRA_MAINNET' || + _to.id === 'PETH_ON_ULTRA_MAINNET' || + _to.id === 'PBORG_ON_ULTRA_MAINNET' || + _to.id === 'PAGA_ON_ULTRA_MAINNET' + ) { const web3 = new Web3() swapBuilder.addDestinationAsset(destinationAsset, 'ultra.swap', web3.utils.utf8ToHex(_address)) } else { diff --git a/src/utils/__tests__/swap-valildator.test.js b/src/utils/__tests__/swap-valildator.test.js index 1426afcd..0c0abc22 100644 --- a/src/utils/__tests__/swap-valildator.test.js +++ b/src/utils/__tests__/swap-valildator.test.js @@ -86,10 +86,19 @@ describe('isValidSwap', () => { ], [ 'USDT', - ['USDT_ON_ALGORAND_MAINNET', 'PUSDT_ON_ALGORAND_MAINNET', 'PUSDT_ON_LIBRE_MAINNET', 'PUSDT_ON_TELOS_MAINNET'], + [ + 'USDT_ON_ALGORAND_MAINNET', + 'PUSDT_ON_ALGORAND_MAINNET', + 'PUSDT_ON_LIBRE_MAINNET', + 'PUSDT_ON_TELOS_MAINNET', + 'PUSDT_ON_ULTRA_MAINNET', + ], ], ['USDT_ON_ALGORAND_MAINNET', ['USDT']], - ['PUSDT_ON_ALGORAND_MAINNET', ['USDT', 'PUSDT_ON_LIBRE_MAINNET', 'PUSDT_ON_TELOS_MAINNET']], + [ + 'PUSDT_ON_ALGORAND_MAINNET', + ['USDT', 'PUSDT_ON_LIBRE_MAINNET', 'PUSDT_ON_TELOS_MAINNET', 'PUSDT_ON_ULTRA_MAINNET'], + ], ['UOS', ['PUOS_ON_ULTRA_MAINNET']], ])('Should determine valid destination assets for %s', (id, expectedIds) => { const from = getAssetById(id)