@bitpay-labs/bitcore-wallet-service 11.11.2 → 11.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/config.ts +8 -0
- package/src/externalservices/coingecko.ts +6 -1
- package/src/externalservices/transak.ts +394 -70
- package/src/lib/blockchainexplorer.ts +4 -0
- package/src/lib/blockchainexplorers/v8.ts +1 -0
- package/src/lib/blockchainmonitor.ts +1 -0
- package/src/lib/chain/arc/index.ts +95 -0
- package/src/lib/chain/eth/index.ts +41 -23
- package/src/lib/chain/index.ts +2 -0
- package/src/lib/common/constants.ts +13 -2
- package/src/lib/common/defaults.ts +31 -0
- package/src/lib/common/utils.ts +18 -1
- package/src/lib/emailservice.ts +3 -1
- package/src/lib/errors/errordefinitions.ts +4 -0
- package/src/lib/model/preferences.ts +4 -0
- package/src/lib/model/tsskeygen.ts +16 -0
- package/src/lib/model/wallet.ts +1 -0
- package/src/lib/pushnotificationsservice.ts +2 -0
- package/src/lib/routes/maintenance.ts +11 -2
- package/src/lib/routes/middleware/authTssRequest.ts +28 -16
- package/src/lib/routes/middleware/verifyTssMessage.ts +4 -1
- package/src/lib/routes/services.ts +8 -2
- package/src/lib/routes/tss.ts +33 -30
- package/src/lib/routes/walletdata.ts +2 -0
- package/src/lib/server.ts +82 -19
- package/src/lib/storage.ts +39 -0
- package/src/lib/tss.ts +111 -7
- package/test/blockchainexplorer.test.ts +7 -0
- package/test/expressapp.test.ts +130 -0
- package/test/integration/externalservices/coinGecko.test.ts +42 -2
- package/test/integration/externalservices/transak.test.ts +545 -135
- package/test/integration/fiatrateservice.test.ts +13 -0
- package/test/integration/helpers.ts +1 -0
- package/test/integration/server.test.ts +192 -4
- package/test/integration/tss.test.ts +428 -0
- package/ts_build/package.json +4 -4
- package/ts_build/src/config.d.ts.map +1 -1
- package/ts_build/src/config.js +8 -0
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/externalservices/coingecko.d.ts.map +1 -1
- package/ts_build/src/externalservices/coingecko.js +6 -1
- package/ts_build/src/externalservices/coingecko.js.map +1 -1
- package/ts_build/src/externalservices/transak.d.ts +28 -2
- package/ts_build/src/externalservices/transak.d.ts.map +1 -1
- package/ts_build/src/externalservices/transak.js +274 -57
- package/ts_build/src/externalservices/transak.js.map +1 -1
- package/ts_build/src/lib/blockchainexplorer.d.ts.map +1 -1
- package/ts_build/src/lib/blockchainexplorer.js +4 -0
- package/ts_build/src/lib/blockchainexplorer.js.map +1 -1
- package/ts_build/src/lib/blockchainexplorers/v8.d.ts.map +1 -1
- package/ts_build/src/lib/blockchainexplorers/v8.js +1 -0
- package/ts_build/src/lib/blockchainexplorers/v8.js.map +1 -1
- package/ts_build/src/lib/blockchainmonitor.d.ts.map +1 -1
- package/ts_build/src/lib/blockchainmonitor.js +1 -0
- package/ts_build/src/lib/blockchainmonitor.js.map +1 -1
- package/ts_build/src/lib/chain/arc/index.d.ts +20 -0
- package/ts_build/src/lib/chain/arc/index.d.ts.map +1 -0
- package/ts_build/src/lib/chain/arc/index.js +95 -0
- package/ts_build/src/lib/chain/arc/index.js.map +1 -0
- package/ts_build/src/lib/chain/eth/index.d.ts +1 -0
- package/ts_build/src/lib/chain/eth/index.d.ts.map +1 -1
- package/ts_build/src/lib/chain/eth/index.js +38 -19
- package/ts_build/src/lib/chain/eth/index.js.map +1 -1
- package/ts_build/src/lib/chain/index.d.ts.map +1 -1
- package/ts_build/src/lib/chain/index.js +2 -0
- package/ts_build/src/lib/chain/index.js.map +1 -1
- package/ts_build/src/lib/common/constants.d.ts +13 -1
- package/ts_build/src/lib/common/constants.d.ts.map +1 -1
- package/ts_build/src/lib/common/constants.js +13 -2
- package/ts_build/src/lib/common/constants.js.map +1 -1
- package/ts_build/src/lib/common/defaults.d.ts +24 -0
- package/ts_build/src/lib/common/defaults.d.ts.map +1 -1
- package/ts_build/src/lib/common/defaults.js +30 -0
- package/ts_build/src/lib/common/defaults.js.map +1 -1
- package/ts_build/src/lib/common/index.d.ts +38 -1
- package/ts_build/src/lib/common/index.d.ts.map +1 -1
- package/ts_build/src/lib/common/utils.d.ts +1 -0
- package/ts_build/src/lib/common/utils.d.ts.map +1 -1
- package/ts_build/src/lib/common/utils.js +16 -1
- package/ts_build/src/lib/common/utils.js.map +1 -1
- package/ts_build/src/lib/emailservice.d.ts.map +1 -1
- package/ts_build/src/lib/emailservice.js +2 -0
- package/ts_build/src/lib/emailservice.js.map +1 -1
- package/ts_build/src/lib/errors/errordefinitions.d.ts +2 -0
- package/ts_build/src/lib/errors/errordefinitions.d.ts.map +1 -1
- package/ts_build/src/lib/errors/errordefinitions.js +2 -0
- package/ts_build/src/lib/errors/errordefinitions.js.map +1 -1
- package/ts_build/src/lib/model/preferences.d.ts +2 -0
- package/ts_build/src/lib/model/preferences.d.ts.map +1 -1
- package/ts_build/src/lib/model/preferences.js +3 -0
- package/ts_build/src/lib/model/preferences.js.map +1 -1
- package/ts_build/src/lib/model/tsskeygen.d.ts +10 -0
- package/ts_build/src/lib/model/tsskeygen.d.ts.map +1 -1
- package/ts_build/src/lib/model/tsskeygen.js +3 -0
- package/ts_build/src/lib/model/tsskeygen.js.map +1 -1
- package/ts_build/src/lib/model/wallet.d.ts.map +1 -1
- package/ts_build/src/lib/model/wallet.js +1 -0
- package/ts_build/src/lib/model/wallet.js.map +1 -1
- package/ts_build/src/lib/pushnotificationsservice.d.ts.map +1 -1
- package/ts_build/src/lib/pushnotificationsservice.js +2 -0
- package/ts_build/src/lib/pushnotificationsservice.js.map +1 -1
- package/ts_build/src/lib/routes/maintenance.d.ts.map +1 -1
- package/ts_build/src/lib/routes/maintenance.js +12 -4
- package/ts_build/src/lib/routes/maintenance.js.map +1 -1
- package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts +6 -2
- package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts.map +1 -1
- package/ts_build/src/lib/routes/middleware/authTssRequest.js +21 -14
- package/ts_build/src/lib/routes/middleware/authTssRequest.js.map +1 -1
- package/ts_build/src/lib/routes/middleware/verifyTssMessage.d.ts.map +1 -1
- package/ts_build/src/lib/routes/middleware/verifyTssMessage.js +2 -1
- package/ts_build/src/lib/routes/middleware/verifyTssMessage.js.map +1 -1
- package/ts_build/src/lib/routes/services.d.ts.map +1 -1
- package/ts_build/src/lib/routes/services.js +7 -2
- package/ts_build/src/lib/routes/services.js.map +1 -1
- package/ts_build/src/lib/routes/tss.d.ts.map +1 -1
- package/ts_build/src/lib/routes/tss.js +32 -30
- package/ts_build/src/lib/routes/tss.js.map +1 -1
- package/ts_build/src/lib/routes/walletdata.d.ts.map +1 -1
- package/ts_build/src/lib/routes/walletdata.js +2 -0
- package/ts_build/src/lib/routes/walletdata.js.map +1 -1
- package/ts_build/src/lib/server.d.ts +23 -2
- package/ts_build/src/lib/server.d.ts.map +1 -1
- package/ts_build/src/lib/server.js +37 -5
- package/ts_build/src/lib/server.js.map +1 -1
- package/ts_build/src/lib/storage.d.ts +9 -0
- package/ts_build/src/lib/storage.d.ts.map +1 -1
- package/ts_build/src/lib/storage.js +26 -0
- package/ts_build/src/lib/storage.js.map +1 -1
- package/ts_build/src/lib/tss.d.ts +12 -0
- package/ts_build/src/lib/tss.d.ts.map +1 -1
- package/ts_build/src/lib/tss.js +64 -5
- package/ts_build/src/lib/tss.js.map +1 -1
- package/ts_build/test/blockchainexplorer.test.js +6 -0
- package/ts_build/test/blockchainexplorer.test.js.map +1 -1
- package/ts_build/test/expressapp.test.js +120 -0
- package/ts_build/test/expressapp.test.js.map +1 -1
- package/ts_build/test/integration/externalservices/coinGecko.test.js +38 -2
- package/ts_build/test/integration/externalservices/coinGecko.test.js.map +1 -1
- package/ts_build/test/integration/externalservices/transak.test.d.ts.map +1 -1
- package/ts_build/test/integration/externalservices/transak.test.js +498 -128
- package/ts_build/test/integration/externalservices/transak.test.js.map +1 -1
- package/ts_build/test/integration/fiatrateservice.test.js +11 -0
- package/ts_build/test/integration/fiatrateservice.test.js.map +1 -1
- package/ts_build/test/integration/helpers.d.ts.map +1 -1
- package/ts_build/test/integration/helpers.js +1 -0
- package/ts_build/test/integration/helpers.js.map +1 -1
- package/ts_build/test/integration/server.test.js +182 -3
- package/ts_build/test/integration/server.test.js.map +1 -1
- package/ts_build/test/integration/tss.test.d.ts.map +1 -1
- package/ts_build/test/integration/tss.test.js +344 -0
- package/ts_build/test/integration/tss.test.js.map +1 -1
|
@@ -931,6 +931,19 @@ describe('Fiat rate service', function() {
|
|
|
931
931
|
});
|
|
932
932
|
});
|
|
933
933
|
});
|
|
934
|
+
it('should fetch and store USD-pegged rates for native USDC on Arc', async function() {
|
|
935
|
+
await util.promisify(service.storage.storeFiatRate).call(service.storage, 'btc', btcRates);
|
|
936
|
+
request.get.yields(null, null, btcRates.map(({ code, value }) => ({ code, rate: value })));
|
|
937
|
+
|
|
938
|
+
await util.promisify(service._fetch).call(service);
|
|
939
|
+
|
|
940
|
+
const storedRate = await util.promisify(service.getRate).call(service, { coin: 'arc', code: 'USD' });
|
|
941
|
+
storedRate.rate.should.equal(1);
|
|
942
|
+
const rates = await util.promisify(service.getRatesByCoin).call(service, { coin: 'arc' });
|
|
943
|
+
rates.find(rate => rate.code === 'USD').rate.should.equal(1);
|
|
944
|
+
rates.find(rate => rate.code === 'EUR').rate.should.equal(0.87);
|
|
945
|
+
request.get.calledWith(sinon.match({ url: sinon.match(/\/rates\/ARC\?/) })).should.equal(false);
|
|
946
|
+
});
|
|
934
947
|
it('should get rate for specific ts', function(done) {
|
|
935
948
|
const clock = sinon.useFakeTimers({ toFake: ['Date'] });
|
|
936
949
|
clock.tick(20);
|
|
@@ -21,6 +21,8 @@ import * as TestData from '../testdata';
|
|
|
21
21
|
import helpers from './helpers';
|
|
22
22
|
import { ClientError } from '../../src/lib/errors/clienterror';
|
|
23
23
|
import { ExpressApp } from '../../src/lib/expressapp';
|
|
24
|
+
import { ERC20Abi } from '../../src/lib/chain/eth/abi-erc20';
|
|
25
|
+
import { type JoinWalletOpts } from '../../src/lib/server';
|
|
24
26
|
|
|
25
27
|
const should = chai.should();
|
|
26
28
|
config.moralis = config.moralis ?? {
|
|
@@ -1120,7 +1122,7 @@ describe('Wallet service', function() {
|
|
|
1120
1122
|
xPubKey: TestData.copayers[0].xPubKey_44H_0H_0H,
|
|
1121
1123
|
requestPubKey: TestData.copayers[0].pubKey_1H_0,
|
|
1122
1124
|
};
|
|
1123
|
-
server.joinWallet(copayerOpts, function(err) {
|
|
1125
|
+
server.joinWallet(copayerOpts as JoinWalletOpts, function(err) {
|
|
1124
1126
|
should.exist(err);
|
|
1125
1127
|
err.message.should.contain('argument: copayerSignature missing');
|
|
1126
1128
|
done();
|
|
@@ -1774,6 +1776,57 @@ describe('Wallet service', function() {
|
|
|
1774
1776
|
wallet.copayers.length.should.equal(0);
|
|
1775
1777
|
});
|
|
1776
1778
|
});
|
|
1779
|
+
|
|
1780
|
+
describe('TSS wallets (concurrent join)', function() {
|
|
1781
|
+
it('should keep a copayer that joins while the wallet is being registered', async function() {
|
|
1782
|
+
const server = new WalletService();
|
|
1783
|
+
const copayerIds = [0, 1].map(i => Model.Copayer.xPubToCopayerId('btc', TestData.copayers[i].xPubKey_44H_0H_0H));
|
|
1784
|
+
|
|
1785
|
+
const session = TssKeyGenModel.create({
|
|
1786
|
+
id: 'tss-join-during-register-test-session',
|
|
1787
|
+
message: { partyId: 0, broadcastMessages: [], p2pMessages: [], publicKey: 'dummy', round: 0 },
|
|
1788
|
+
n: 2,
|
|
1789
|
+
copayerId: copayerIds[0],
|
|
1790
|
+
version: Defaults.TSS_KEYGEN_SCHEME_VERSION
|
|
1791
|
+
});
|
|
1792
|
+
session.participants[1] = copayerIds[1];
|
|
1793
|
+
session.sharedPublicKey = 'dummy-shared-public-key';
|
|
1794
|
+
await server.storage.db.collection('tss_keygen').deleteMany({ id: session.id });
|
|
1795
|
+
await server.storage.storeTssKeyGenSession({ doc: session });
|
|
1796
|
+
|
|
1797
|
+
const walletId = await util.promisify(server.createWallet).call(server, {
|
|
1798
|
+
name: 'tss wallet',
|
|
1799
|
+
m: 1,
|
|
1800
|
+
n: 1,
|
|
1801
|
+
pubKey: TestData.keyPair.pub,
|
|
1802
|
+
coin: 'btc',
|
|
1803
|
+
tssKeyId: session.id,
|
|
1804
|
+
});
|
|
1805
|
+
const [creatorOpts, joinerOpts] = [0, 1].map(i => helpers.getSignedCopayerOpts({
|
|
1806
|
+
walletId,
|
|
1807
|
+
name: 'copayer ' + (i + 1),
|
|
1808
|
+
xPubKey: TestData.copayers[i].xPubKey_44H_0H_0H,
|
|
1809
|
+
requestPubKey: TestData.copayers[i].pubKey_1H_0,
|
|
1810
|
+
}));
|
|
1811
|
+
const { copayerId } = await util.promisify(server.joinWallet).call(server, creatorOpts);
|
|
1812
|
+
const creatorServer = await helpers.getAuthServer(copayerId);
|
|
1813
|
+
creatorServer.checkWalletSync = function(a, b, simple, cb) {
|
|
1814
|
+
if (simple) return cb(null, false);
|
|
1815
|
+
return cb(null, true);
|
|
1816
|
+
};
|
|
1817
|
+
|
|
1818
|
+
blockchainExplorer.register = sinon.stub().callsFake((wallet, cb) => server.joinWallet(joinerOpts, cb));
|
|
1819
|
+
await util.promisify(creatorServer.getStatus).call(creatorServer, { includeExtendedInfo: true });
|
|
1820
|
+
|
|
1821
|
+
blockchainExplorer.register.calledOnce.should.equal(true);
|
|
1822
|
+
const registeredWallet = blockchainExplorer.register.firstCall.args[0];
|
|
1823
|
+
const wallet = await util.promisify(server.storage.fetchWallet).call(server.storage, walletId);
|
|
1824
|
+
wallet.copayers.length.should.equal(2);
|
|
1825
|
+
wallet.beRegistered.should.equal(true);
|
|
1826
|
+
wallet.beAuthPrivateKey2.should.equal(registeredWallet.beAuthPrivateKey2);
|
|
1827
|
+
wallet.beAuthPublicKey2.should.equal(registeredWallet.beAuthPublicKey2);
|
|
1828
|
+
});
|
|
1829
|
+
});
|
|
1777
1830
|
});
|
|
1778
1831
|
|
|
1779
1832
|
describe('#removeWallet', function() {
|
|
@@ -2697,6 +2750,29 @@ describe('Wallet service', function() {
|
|
|
2697
2750
|
({ server, wallet } = await helpers.createAndJoinWallet(1, 1, { coin: 'eth' }));
|
|
2698
2751
|
});
|
|
2699
2752
|
|
|
2753
|
+
it('should save and merge Arc token preferences without linking native USDC', async function() {
|
|
2754
|
+
({ server } = await helpers.createAndJoinWallet(1, 1, { coin: 'arc', network: 'livenet' }));
|
|
2755
|
+
await util.promisify(server.savePreferences).call(server, { arcTokenAddresses: [TOKENS[0]], language: 'es' });
|
|
2756
|
+
await util.promisify(server.savePreferences).call(server, {
|
|
2757
|
+
arcTokenAddresses: [TOKENS[1], CWC.ethers.getAddress(TOKENS[0])],
|
|
2758
|
+
});
|
|
2759
|
+
let preferences = await util.promisify(server.getPreferences).call(server, {});
|
|
2760
|
+
preferences.arcTokenAddresses.should.deep.equal(TOKENS);
|
|
2761
|
+
preferences.language.should.equal('es');
|
|
2762
|
+
|
|
2763
|
+
try {
|
|
2764
|
+
await util.promisify(server.savePreferences).call(server, {
|
|
2765
|
+
arcTokenAddresses: [TOKENS[0], CWC.Constants.ARC.USDC_CONTRACT_ADDRESS], language: 'en',
|
|
2766
|
+
});
|
|
2767
|
+
should.fail('Expected native USDC token preference rejection');
|
|
2768
|
+
} catch (err) {
|
|
2769
|
+
err.message.toString().should.contain('arcTokenAddresses');
|
|
2770
|
+
}
|
|
2771
|
+
preferences = await util.promisify(server.getPreferences).call(server, {});
|
|
2772
|
+
preferences.arcTokenAddresses.should.deep.equal(TOKENS);
|
|
2773
|
+
preferences.language.should.equal('es');
|
|
2774
|
+
});
|
|
2775
|
+
|
|
2700
2776
|
it('should save & retrieve preferences', function(done) {
|
|
2701
2777
|
server.savePreferences({
|
|
2702
2778
|
email: 'dummy@dummy.com',
|
|
@@ -2896,7 +2972,8 @@ describe('Wallet service', function() {
|
|
|
2896
2972
|
unit: 'xxxxx',
|
|
2897
2973
|
},
|
|
2898
2974
|
expected: 'unit'
|
|
2899
|
-
},]
|
|
2975
|
+
}, ...['not-an-array', ['invalid']]
|
|
2976
|
+
.map(arcTokenAddresses => ({ preferences: { arcTokenAddresses }, expected: 'arcTokenAddresses' }))];
|
|
2900
2977
|
|
|
2901
2978
|
for (const item of invalid) {
|
|
2902
2979
|
try {
|
|
@@ -6169,6 +6246,113 @@ describe('Wallet service', function() {
|
|
|
6169
6246
|
});
|
|
6170
6247
|
});
|
|
6171
6248
|
|
|
6249
|
+
for (const [network, chainId] of [['livenet', 5042n], ['testnet', 5042002n]] as const) {
|
|
6250
|
+
describe(`#createTX ARC ${network}`, () => {
|
|
6251
|
+
let server: WalletService;
|
|
6252
|
+
let from: string;
|
|
6253
|
+
const destination = '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A';
|
|
6254
|
+
const usdc = new CWC.ethers.Interface(ERC20Abi);
|
|
6255
|
+
const contractOpts = (data: string) => makeOpts({
|
|
6256
|
+
outputs: [{ toAddress: CWC.Constants.ARC.USDC_CONTRACT_ADDRESS, amount: 0, gasLimit: 100000, data }]
|
|
6257
|
+
});
|
|
6258
|
+
const makeOpts = (overrides = {}) => ({
|
|
6259
|
+
outputs: [{ toAddress: destination, amount: 1e18, gasLimit: 21000 }],
|
|
6260
|
+
nonce: 0, feeLevel: 'normal', ...overrides
|
|
6261
|
+
});
|
|
6262
|
+
|
|
6263
|
+
beforeEach(async () => {
|
|
6264
|
+
({ server } = await helpers.createAndJoinWallet(1, 1, { coin: 'arc', network }));
|
|
6265
|
+
from = (await util.promisify(server.createAddress).call(server, {})).address;
|
|
6266
|
+
blockchainExplorer.getBalance = sinon.stub().callsArgWith(1, null, { balance: 2e18, confirmed: 2e18, unconfirmed: 0 });
|
|
6267
|
+
helpers.stubFeeLevels({ 1: 25000000000, 2: 25000000000, 3: 25000000000, 4: 25000000000 }, true, 'arc');
|
|
6268
|
+
});
|
|
6269
|
+
|
|
6270
|
+
for (const [txType, sendMax] of [[0, false], [2, false], [2, true]] as const) {
|
|
6271
|
+
it(`should publish, sign and submit a type ${txType} native USDC ${sendMax ? 'send-max ' : ''}proposal`, async () => {
|
|
6272
|
+
const maxGasFee = sendMax ? 31000000000 : 30000000000;
|
|
6273
|
+
sinon.stub(server, 'estimateFee').resolves(maxGasFee).onFirstCall().resolves(30000000000);
|
|
6274
|
+
sinon.stub(server, 'estimatePriorityFee').resolves(0);
|
|
6275
|
+
const fee = (txType === 2 ? maxGasFee : 25000000000) * 21000;
|
|
6276
|
+
const amount = sendMax ? 2e18 - fee : 1e18;
|
|
6277
|
+
const txp = await util.promisify(server.createTx).call(server, makeOpts({ txType, sendMax,
|
|
6278
|
+
outputs: [{ toAddress: destination, amount: sendMax ? null : amount, gasLimit: 21000 }] }));
|
|
6279
|
+
txp.fee.should.equal(fee);
|
|
6280
|
+
txp.amount.should.equal(amount);
|
|
6281
|
+
await util.promisify(server.publishTx).call(server, helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0));
|
|
6282
|
+
await util.promisify(server.signTx).call(server, { txProposalId: txp.id, signatures: helpers.clientSign(txp, TestData.copayers[0].xPrivKey_44H_0H_0H) });
|
|
6283
|
+
const accepted = await util.promisify(server.getTx).call(server, { txProposalId: txp.id });
|
|
6284
|
+
accepted.status.should.equal('accepted');
|
|
6285
|
+
const [raw] = accepted.getRawTx();
|
|
6286
|
+
const signed = CWC.ethers.Transaction.from(raw);
|
|
6287
|
+
signed.chainId.should.equal(chainId);
|
|
6288
|
+
signed.value.should.equal(BigInt(amount));
|
|
6289
|
+
BigInt(txp.fee).should.equal((signed.maxFeePerGas ?? signed.gasPrice) * signed.gasLimit);
|
|
6290
|
+
signed.isSigned().should.equal(true);
|
|
6291
|
+
helpers.stubBroadcast(accepted.txid);
|
|
6292
|
+
await util.promisify(server.broadcastTx).call(server, { txProposalId: txp.id });
|
|
6293
|
+
blockchainExplorer.broadcast.firstCall.args[0].should.deep.equal([raw]);
|
|
6294
|
+
(await util.promisify(server.getTx).call(server, { txProposalId: txp.id })).status.should.equal('broadcasted');
|
|
6295
|
+
});
|
|
6296
|
+
}
|
|
6297
|
+
|
|
6298
|
+
it('should reserve wallet-owned USDC contract debits and release them when removed', async () => {
|
|
6299
|
+
for (const [method, args, debit, legacyData] of [
|
|
6300
|
+
['transfer', [destination, 1000000n], 1e18],
|
|
6301
|
+
['transferFrom', [from, destination, 1000000n], 1e18],
|
|
6302
|
+
['transferFrom', [destination, from, 1000000n], 0],
|
|
6303
|
+
['approve', [destination, 1000000n], 0],
|
|
6304
|
+
['approve', [destination, 1000000n], 1e18, usdc.encodeFunctionData('transfer', [destination, 1000000n])]
|
|
6305
|
+
] as Array<[string, any[], number, string?]>) {
|
|
6306
|
+
const data = usdc.encodeFunctionData(method, args);
|
|
6307
|
+
const txp = await util.promisify(server.createTx).call(server, { ...contractOpts(data), data: legacyData });
|
|
6308
|
+
txp.amount.should.equal(0);
|
|
6309
|
+
txp.outputs[0].amount.should.equal(0);
|
|
6310
|
+
txp.outputs[0].data.should.equal(data);
|
|
6311
|
+
CWC.ethers.Transaction.from(txp.getRawTx()[0]).data.should.equal(legacyData || data);
|
|
6312
|
+
await util.promisify(server.publishTx).call(server, helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0));
|
|
6313
|
+
const balance = await util.promisify(server.getBalance).call(server, {});
|
|
6314
|
+
balance.lockedAmount.should.equal(debit + txp.fee);
|
|
6315
|
+
balance.availableAmount.should.equal(2e18 - debit - txp.fee);
|
|
6316
|
+
if (debit) {
|
|
6317
|
+
try {
|
|
6318
|
+
await util.promisify(server.createTx).call(server, makeOpts({ nonce: 1,
|
|
6319
|
+
outputs: [{ toAddress: destination, amount: 1.5e18, gasLimit: 21000 }] }));
|
|
6320
|
+
should.fail('Expected pending USDC funds to be unavailable');
|
|
6321
|
+
} catch (err) {
|
|
6322
|
+
err.code.should.equal('LOCKED_FUNDS');
|
|
6323
|
+
}
|
|
6324
|
+
}
|
|
6325
|
+
await util.promisify(server.removePendingTx).call(server, { txProposalId: txp.id });
|
|
6326
|
+
(await util.promisify(server.getBalance).call(server, {})).lockedAmount.should.equal(0);
|
|
6327
|
+
}
|
|
6328
|
+
});
|
|
6329
|
+
|
|
6330
|
+
it('should reject underpriced proposals, duplicate USDC token views and zero-address transfers', async () => {
|
|
6331
|
+
try {
|
|
6332
|
+
await util.promisify(server.getBalance).call(server, { tokenAddress: CWC.Constants.ARC.USDC_CONTRACT_ADDRESS });
|
|
6333
|
+
throw new Error('Expected duplicate token balance rejection');
|
|
6334
|
+
} catch (err) {
|
|
6335
|
+
err.message.should.contain('omit tokenAddress');
|
|
6336
|
+
}
|
|
6337
|
+
for (const [opts, message] of [
|
|
6338
|
+
[makeOpts({ feeLevel: undefined, feePerKb: 10000000000 }), 'at least 20 gwei'],
|
|
6339
|
+
[makeOpts({ tokenAddress: CWC.Constants.ARC.USDC_CONTRACT_ADDRESS }), 'omit tokenAddress'],
|
|
6340
|
+
[contractOpts(usdc.encodeFunctionData('transfer', [destination, 3000000n])), 'Insufficient funds'],
|
|
6341
|
+
[contractOpts(usdc.encodeFunctionData('transfer', [destination, 2000000n])), 'Insufficient funds for fee'],
|
|
6342
|
+
[contractOpts(usdc.getFunction('transfer').selector), 'Invalid Arc USDC contract call data'],
|
|
6343
|
+
[makeOpts({ outputs: [{ toAddress: '0x0000000000000000000000000000000000000000', amount: 1e18 }] }), 'zero address']
|
|
6344
|
+
] as Array<[any, string]>) {
|
|
6345
|
+
try {
|
|
6346
|
+
await util.promisify(server.createTx).call(server, opts);
|
|
6347
|
+
throw new Error('Expected proposal rejection');
|
|
6348
|
+
} catch (err) {
|
|
6349
|
+
err.message.should.contain(message);
|
|
6350
|
+
}
|
|
6351
|
+
}
|
|
6352
|
+
});
|
|
6353
|
+
});
|
|
6354
|
+
}
|
|
6355
|
+
|
|
6172
6356
|
describe('#createTX ETH Only tests', () => {
|
|
6173
6357
|
let server: WalletService;
|
|
6174
6358
|
let wallet: Model.Wallet;
|
|
@@ -6362,8 +6546,8 @@ describe('Wallet service', function() {
|
|
|
6362
6546
|
sinon.stub(server, 'estimatePriorityFee').resolves(1000000000);
|
|
6363
6547
|
const txp = await util.promisify(server.createTx).call(server, makeOpts({ txType: 2 }));
|
|
6364
6548
|
txp.feeLevel.should.equal('normal');
|
|
6365
|
-
txp.gasPrice.should.equal(
|
|
6366
|
-
txp.fee.should.equal(
|
|
6549
|
+
txp.gasPrice.should.equal(4500000000);
|
|
6550
|
+
txp.fee.should.equal(450000000000000);
|
|
6367
6551
|
txp.maxGasFee.should.equal(4500000000);
|
|
6368
6552
|
txp.priorityGasFee.should.equal(1000000000);
|
|
6369
6553
|
const [raw] = txp.getRawTx();
|
|
@@ -6425,6 +6609,10 @@ describe('Wallet service', function() {
|
|
|
6425
6609
|
await helpers.stubUtxos(server, wallet, [0.0002]);
|
|
6426
6610
|
const defaultTxp = await util.promisify(server.createTx).call(server, makeOpts({ tokenAddress }));
|
|
6427
6611
|
defaultTxp.fee.should.equal(100000000000000);
|
|
6612
|
+
sinon.stub(server, 'estimateFee').resolves(3000000000);
|
|
6613
|
+
sinon.stub(server, 'estimatePriorityFee').resolves(1000000000);
|
|
6614
|
+
await assert.rejects(util.promisify(server.createTx).call(server, makeOpts({ txType: 2, tokenAddress })),
|
|
6615
|
+
{ code: tokenAddress ? 'INSUFFICIENT_ETH_FEE' : 'INSUFFICIENT_FUNDS_FOR_FEE' });
|
|
6428
6616
|
await assert.rejects(util.promisify(server.createTx).call(server, makeOpts({
|
|
6429
6617
|
txType: 2, maxGasFee: 3000000000, priorityGasFee: 1000000000, tokenAddress
|
|
6430
6618
|
})), { code: tokenAddress ? 'INSUFFICIENT_ETH_FEE' : 'INSUFFICIENT_FUNDS_FOR_FEE' });
|