@portal-hq/web 3.16.0 → 3.17.0-alpha.0
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/lib/commonjs/index.js +294 -0
- package/lib/commonjs/index.test.js +231 -0
- package/lib/commonjs/mpc/index.js +27 -1
- package/lib/commonjs/mpc/index.test.js +134 -0
- package/lib/commonjs/shared/types/accountAbstraction.js +2 -0
- package/lib/commonjs/shared/types/index.js +2 -0
- package/lib/esm/index.js +294 -0
- package/lib/esm/index.test.js +233 -2
- package/lib/esm/mpc/index.js +27 -1
- package/lib/esm/mpc/index.test.js +135 -1
- package/lib/esm/shared/types/accountAbstraction.js +1 -0
- package/lib/esm/shared/types/index.js +2 -0
- package/package.json +3 -2
- package/src/__mocks/constants.ts +93 -0
- package/src/__mocks/portal/mpc.ts +11 -0
- package/src/index.test.ts +473 -1
- package/src/index.ts +454 -0
- package/src/mpc/index.test.ts +164 -0
- package/src/mpc/index.ts +36 -1
- package/src/shared/types/accountAbstraction.ts +122 -0
- package/src/shared/types/common.ts +3 -0
- package/src/shared/types/index.ts +3 -0
package/lib/esm/index.test.js
CHANGED
|
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
|
-
import Portal, { BackupMethods, GetTransactionsOrder } from '.';
|
|
14
|
-
import { mockAddress, mockBackupConfig, mockBlockHashResponse, mockBuiltTronTransaction, mockCipherText, mockClientResponse, mockEip155Address, mockEjectResult, mockEjectPrivateKeysResult, mockEthRpcUrl, mockEthTransaction, mockMpcBackupResponse, mockOrgBackupShare, mockOrgBackupShares, mockQuoteArgs, mockRpcConfig, mockSharesOnDevice, mockSignedHash, mockSolanaAddress, mockSolRpcUrl, mockTronAddress, } from './__mocks/constants';
|
|
13
|
+
import Portal, { BackupMethods, GetTransactionsOrder, PortalCurve } from '.';
|
|
14
|
+
import { mockAddress, mockBackupConfig, mockBlockHashResponse, mockBuiltEip155Transaction, mockBuiltEip155TransactionNative, mockBuiltTronTransaction, mockBuildBatchedUserOpRequest, mockBuildBatchedUserOpResponse, mockBroadcastBatchedUserOpRequest, mockBroadcastBatchedUserOpResponse, mockCipherText, mockClientResponse, mockEip155Address, mockEjectResult, mockEjectPrivateKeysResult, mockEthRpcUrl, mockEthTransaction, mockMpcBackupResponse, mockOrgBackupShare, mockOrgBackupShares, mockQuoteArgs, mockRpcConfig, mockSendBatchUserOpRequest, mockSharesOnDevice, mockSignedHash, mockSolanaAddress, mockSolRpcUrl, mockTronAddress, } from './__mocks/constants';
|
|
15
15
|
import mpcMock from './__mocks/portal/mpc';
|
|
16
16
|
import providerMock from './__mocks/portal/provider';
|
|
17
17
|
/**
|
|
@@ -719,6 +719,237 @@ describe('Portal', () => {
|
|
|
719
719
|
expect(portal.mpc.getSources).toHaveBeenCalledWith('eip155:1', 'test');
|
|
720
720
|
}));
|
|
721
721
|
});
|
|
722
|
+
describe('buildBatchedUserOp', () => {
|
|
723
|
+
it('should correctly call mpc.accountAbstractionBuildBatchedUserOp', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
724
|
+
yield portal.buildBatchedUserOp(mockBuildBatchedUserOpRequest);
|
|
725
|
+
expect(portal.mpc.accountAbstractionBuildBatchedUserOp).toHaveBeenCalledTimes(1);
|
|
726
|
+
expect(portal.mpc.accountAbstractionBuildBatchedUserOp).toHaveBeenCalledWith(mockBuildBatchedUserOpRequest);
|
|
727
|
+
}));
|
|
728
|
+
});
|
|
729
|
+
describe('broadcastBatchedUserOp', () => {
|
|
730
|
+
it('should correctly call mpc.accountAbstractionBroadcastBatchedUserOp', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
731
|
+
yield portal.broadcastBatchedUserOp(mockBroadcastBatchedUserOpRequest);
|
|
732
|
+
expect(portal.mpc.accountAbstractionBroadcastBatchedUserOp).toHaveBeenCalledTimes(1);
|
|
733
|
+
expect(portal.mpc.accountAbstractionBroadcastBatchedUserOp).toHaveBeenCalledWith(mockBroadcastBatchedUserOpRequest);
|
|
734
|
+
}));
|
|
735
|
+
});
|
|
736
|
+
describe('sendBatchUserOp', () => {
|
|
737
|
+
it('should build, sign, and broadcast a batched UserOperation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
738
|
+
const result = yield portal.sendBatchUserOp(mockSendBatchUserOpRequest);
|
|
739
|
+
expect(result).toEqual(expect.objectContaining({
|
|
740
|
+
data: expect.objectContaining({ userOpHash: expect.any(String) }),
|
|
741
|
+
metadata: expect.objectContaining({ chainId: expect.any(String) }),
|
|
742
|
+
}));
|
|
743
|
+
// buildTransaction called once per transaction descriptor
|
|
744
|
+
expect(portal.mpc.buildTransaction).toHaveBeenCalledTimes(2);
|
|
745
|
+
expect(portal.mpc.buildTransaction).toHaveBeenCalledWith(mockSendBatchUserOpRequest.chain, mockSendBatchUserOpRequest.transactions[0].to, mockSendBatchUserOpRequest.transactions[0].token, mockSendBatchUserOpRequest.transactions[0].value, expect.any(String));
|
|
746
|
+
expect(portal.mpc.buildTransaction).toHaveBeenCalledWith(mockSendBatchUserOpRequest.chain, mockSendBatchUserOpRequest.transactions[1].to, mockSendBatchUserOpRequest.transactions[1].token, mockSendBatchUserOpRequest.transactions[1].value, expect.any(String));
|
|
747
|
+
// buildBatchedUserOp called with ERC-20 call shape (no value field) and the shared traceId
|
|
748
|
+
expect(portal.mpc.accountAbstractionBuildBatchedUserOp).toHaveBeenCalledTimes(1);
|
|
749
|
+
expect(portal.mpc.accountAbstractionBuildBatchedUserOp).toHaveBeenCalledWith({
|
|
750
|
+
chain: mockSendBatchUserOpRequest.chain,
|
|
751
|
+
calls: [
|
|
752
|
+
{
|
|
753
|
+
to: mockBuiltEip155Transaction.transaction.to,
|
|
754
|
+
data: mockBuiltEip155Transaction.transaction.data,
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
to: mockBuiltEip155Transaction.transaction.to,
|
|
758
|
+
data: mockBuiltEip155Transaction.transaction.data,
|
|
759
|
+
},
|
|
760
|
+
],
|
|
761
|
+
}, expect.any(String));
|
|
762
|
+
// rawSign called with SECP256K1 and the userOpHash with 0x prefix stripped
|
|
763
|
+
expect(portal.mpc.rawSign).toHaveBeenCalledTimes(1);
|
|
764
|
+
expect(portal.mpc.rawSign).toHaveBeenCalledWith(PortalCurve.SECP256K1, mockBuildBatchedUserOpResponse.data.userOpHash.slice(2), { signatureApprovalMemo: undefined, traceId: expect.any(String) });
|
|
765
|
+
// broadcastBatchedUserOp called with the built userOperation and signature, and the shared traceId
|
|
766
|
+
expect(portal.mpc.accountAbstractionBroadcastBatchedUserOp).toHaveBeenCalledTimes(1);
|
|
767
|
+
expect(portal.mpc.accountAbstractionBroadcastBatchedUserOp).toHaveBeenCalledWith({
|
|
768
|
+
chain: mockSendBatchUserOpRequest.chain,
|
|
769
|
+
userOperation: mockBuildBatchedUserOpResponse.data.userOperation,
|
|
770
|
+
signature: mockSignedHash,
|
|
771
|
+
}, expect.any(String));
|
|
772
|
+
}));
|
|
773
|
+
it('should propagate the same traceId to buildBatchedUserOp and broadcastBatchedUserOp', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
774
|
+
yield portal.sendBatchUserOp(mockSendBatchUserOpRequest);
|
|
775
|
+
const buildTraceId = portal.mpc.accountAbstractionBuildBatchedUserOp.mock.calls[0][1];
|
|
776
|
+
const broadcastTraceId = portal.mpc.accountAbstractionBroadcastBatchedUserOp.mock.calls[0][1];
|
|
777
|
+
expect(typeof buildTraceId).toBe('string');
|
|
778
|
+
expect(buildTraceId).toEqual(broadcastTraceId);
|
|
779
|
+
}));
|
|
780
|
+
it('should include value in the call for native ETH transfers', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
781
|
+
;
|
|
782
|
+
portal.mpc.buildTransaction.mockResolvedValueOnce(mockBuiltEip155TransactionNative);
|
|
783
|
+
yield portal.sendBatchUserOp({
|
|
784
|
+
chain: 'eip155:1',
|
|
785
|
+
transactions: [{ token: 'ETH', value: '0.1', to: '0x1111111111111111111111111111111111111111' }],
|
|
786
|
+
});
|
|
787
|
+
expect(portal.mpc.accountAbstractionBuildBatchedUserOp).toHaveBeenCalledWith({
|
|
788
|
+
chain: 'eip155:1',
|
|
789
|
+
calls: [
|
|
790
|
+
{
|
|
791
|
+
to: mockBuiltEip155TransactionNative.transaction.to,
|
|
792
|
+
data: '0x',
|
|
793
|
+
value: mockBuiltEip155TransactionNative.metadata.rawAmount,
|
|
794
|
+
},
|
|
795
|
+
],
|
|
796
|
+
}, expect.any(String));
|
|
797
|
+
}));
|
|
798
|
+
it('should not include value in the call for ERC-20 transfers', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
799
|
+
yield portal.sendBatchUserOp({
|
|
800
|
+
chain: 'eip155:1',
|
|
801
|
+
transactions: [{ token: 'USDC', value: '1.0', to: '0x1111111111111111111111111111111111111111' }],
|
|
802
|
+
});
|
|
803
|
+
const calls = portal.mpc.accountAbstractionBuildBatchedUserOp.mock.calls[0][0].calls;
|
|
804
|
+
expect(calls[0]).not.toHaveProperty('value');
|
|
805
|
+
}));
|
|
806
|
+
it('should forward signatureApprovalMemo to rawSign', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
807
|
+
yield portal.sendBatchUserOp(Object.assign(Object.assign({}, mockSendBatchUserOpRequest), { signatureApprovalMemo: 'approve this batch' }));
|
|
808
|
+
expect(portal.mpc.rawSign).toHaveBeenCalledWith(PortalCurve.SECP256K1, expect.any(String), { signatureApprovalMemo: 'approve this batch', traceId: expect.any(String) });
|
|
809
|
+
}));
|
|
810
|
+
it('should throw if chain is not eip155', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
811
|
+
yield expect(portal.sendBatchUserOp(Object.assign(Object.assign({}, mockSendBatchUserOpRequest), { chain: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' }))).rejects.toThrow('[Portal.sendBatchUserOp] UserOperations are only supported on EIP-155 (EVM) chains');
|
|
812
|
+
}));
|
|
813
|
+
it('should throw if transactions array is empty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
814
|
+
yield expect(portal.sendBatchUserOp(Object.assign(Object.assign({}, mockSendBatchUserOpRequest), { transactions: [] }))).rejects.toThrow('[Portal.sendBatchUserOp] transactions must contain at least one transaction');
|
|
815
|
+
}));
|
|
816
|
+
it('should throw with index context if buildTransaction fails for transaction 0', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
817
|
+
;
|
|
818
|
+
portal.mpc.buildTransaction.mockRejectedValueOnce(new Error('Network error'));
|
|
819
|
+
yield expect(portal.sendBatchUserOp({
|
|
820
|
+
chain: 'eip155:1',
|
|
821
|
+
transactions: [{ token: 'USDC', value: '1.0', to: '0x1111111111111111111111111111111111111111' }],
|
|
822
|
+
})).rejects.toThrow('[Portal.sendBatchUserOp] Failed to build call for transaction at index 0: Network error');
|
|
823
|
+
}));
|
|
824
|
+
it('should throw with index context if buildTransaction fails for transaction 1', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
825
|
+
;
|
|
826
|
+
portal.mpc.buildTransaction
|
|
827
|
+
.mockResolvedValueOnce(mockBuiltEip155Transaction)
|
|
828
|
+
.mockRejectedValueOnce(new Error('Network error'));
|
|
829
|
+
yield expect(portal.sendBatchUserOp(mockSendBatchUserOpRequest)).rejects.toThrow('[Portal.sendBatchUserOp] Failed to build call for transaction at index 1: Network error');
|
|
830
|
+
}));
|
|
831
|
+
it('should throw if buildBatchedUserOp fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
832
|
+
;
|
|
833
|
+
portal.mpc.accountAbstractionBuildBatchedUserOp.mockRejectedValueOnce(new Error('UserOp build failed'));
|
|
834
|
+
yield expect(portal.sendBatchUserOp(mockSendBatchUserOpRequest)).rejects.toThrow('[Portal.sendBatchUserOp] Failed to build UserOperation: UserOp build failed');
|
|
835
|
+
}));
|
|
836
|
+
it('should throw if rawSign fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
837
|
+
;
|
|
838
|
+
portal.mpc.rawSign.mockRejectedValueOnce(new Error('Signing failed'));
|
|
839
|
+
yield expect(portal.sendBatchUserOp(mockSendBatchUserOpRequest)).rejects.toThrow('[Portal.sendBatchUserOp] Failed to sign userOpHash: Signing failed');
|
|
840
|
+
}));
|
|
841
|
+
it('should throw if broadcastBatchedUserOp fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
842
|
+
;
|
|
843
|
+
portal.mpc.accountAbstractionBroadcastBatchedUserOp.mockRejectedValueOnce(new Error('Broadcast failed'));
|
|
844
|
+
yield expect(portal.sendBatchUserOp(mockSendBatchUserOpRequest)).rejects.toThrow('[Portal.sendBatchUserOp] Failed to broadcast UserOperation: Broadcast failed');
|
|
845
|
+
}));
|
|
846
|
+
});
|
|
847
|
+
describe('sendBatchedAssets', () => {
|
|
848
|
+
const feeRecipient = '0x2222222222222222222222222222222222222222';
|
|
849
|
+
const baseRequest = {
|
|
850
|
+
chain: 'eip155:1',
|
|
851
|
+
transactions: [
|
|
852
|
+
{
|
|
853
|
+
token: 'USDC',
|
|
854
|
+
value: '1.0',
|
|
855
|
+
to: '0x1111111111111111111111111111111111111111',
|
|
856
|
+
},
|
|
857
|
+
],
|
|
858
|
+
};
|
|
859
|
+
it('should build twice, convert gas to a fee, sign, and broadcast', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
860
|
+
const convertGasToFeeAmount = jest.fn().mockResolvedValue('0.5');
|
|
861
|
+
const result = yield portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: { feeToken: 'USDC', feeRecipient, convertGasToFeeAmount } }));
|
|
862
|
+
expect(result).toEqual(mockBroadcastBatchedUserOpResponse);
|
|
863
|
+
// Estimation pass + final pass = 2 builds.
|
|
864
|
+
expect(portal.mpc.accountAbstractionBuildBatchedUserOp).toHaveBeenCalledTimes(2);
|
|
865
|
+
// buildTransaction: 1 user tx + 1 placeholder fee + 1 real fee = 3.
|
|
866
|
+
expect(portal.mpc.buildTransaction).toHaveBeenCalledTimes(3);
|
|
867
|
+
// Conversion called once with gasCostWei = totalGas(100000) * maxFeePerGas(1e9).
|
|
868
|
+
expect(convertGasToFeeAmount).toHaveBeenCalledTimes(1);
|
|
869
|
+
expect(convertGasToFeeAmount).toHaveBeenCalledWith(BigInt('100000000000000'));
|
|
870
|
+
// Placeholder fee call built with the default '0.01'; real fee call with '0.5'.
|
|
871
|
+
expect(portal.mpc.buildTransaction).toHaveBeenCalledWith('eip155:1', feeRecipient, 'USDC', '0.01', expect.any(String));
|
|
872
|
+
expect(portal.mpc.buildTransaction).toHaveBeenCalledWith('eip155:1', feeRecipient, 'USDC', '0.5', expect.any(String));
|
|
873
|
+
expect(portal.mpc.rawSign).toHaveBeenCalledTimes(1);
|
|
874
|
+
expect(portal.mpc.accountAbstractionBroadcastBatchedUserOp).toHaveBeenCalledTimes(1);
|
|
875
|
+
}));
|
|
876
|
+
it('should apply bufferBps to the gas cost before conversion', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
877
|
+
const convertGasToFeeAmount = jest.fn().mockResolvedValue('0.6');
|
|
878
|
+
yield portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: {
|
|
879
|
+
feeToken: 'USDC',
|
|
880
|
+
feeRecipient,
|
|
881
|
+
convertGasToFeeAmount,
|
|
882
|
+
bufferBps: 1000, // +10%
|
|
883
|
+
} }));
|
|
884
|
+
// 1e14 * 11000 / 10000 = 1.1e14
|
|
885
|
+
expect(convertGasToFeeAmount).toHaveBeenCalledWith(BigInt('110000000000000'));
|
|
886
|
+
}));
|
|
887
|
+
it('should throw if the build response is missing estimatedGasCostWei', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
888
|
+
const noGasCost = Object.assign(Object.assign({}, mockBuildBatchedUserOpResponse), { metadata: { chainId: 'eip155:1' } });
|
|
889
|
+
portal.mpc.accountAbstractionBuildBatchedUserOp.mockResolvedValueOnce(noGasCost);
|
|
890
|
+
const convertGasToFeeAmount = jest.fn();
|
|
891
|
+
yield expect(portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: { feeToken: 'USDC', feeRecipient, convertGasToFeeAmount } }))).rejects.toThrow('[Portal.sendBatchedAssets] build response is missing metadata.estimatedGasCostWei');
|
|
892
|
+
// Conversion should never run if we can't determine the gas cost.
|
|
893
|
+
expect(convertGasToFeeAmount).not.toHaveBeenCalled();
|
|
894
|
+
}));
|
|
895
|
+
it('should throw if the estimated gas cost is 0 (e.g. Ultra Relay zero-fee path)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
896
|
+
const zeroCost = Object.assign(Object.assign({}, mockBuildBatchedUserOpResponse), { metadata: {
|
|
897
|
+
chainId: 'eip155:1',
|
|
898
|
+
totalGas: '2000000',
|
|
899
|
+
maxFeePerGas: '0',
|
|
900
|
+
estimatedGasCostWei: '0',
|
|
901
|
+
} });
|
|
902
|
+
portal.mpc.accountAbstractionBuildBatchedUserOp.mockResolvedValueOnce(zeroCost);
|
|
903
|
+
const convertGasToFeeAmount = jest.fn();
|
|
904
|
+
yield expect(portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: { feeToken: 'USDC', feeRecipient, convertGasToFeeAmount } }))).rejects.toThrow('[Portal.sendBatchedAssets] Estimated gas cost is 0');
|
|
905
|
+
expect(convertGasToFeeAmount).not.toHaveBeenCalled();
|
|
906
|
+
}));
|
|
907
|
+
it('should reuse the same traceId across both builds', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
908
|
+
const convertGasToFeeAmount = jest.fn().mockResolvedValue('0.5');
|
|
909
|
+
yield portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: { feeToken: 'USDC', feeRecipient, convertGasToFeeAmount } }));
|
|
910
|
+
const calls = portal.mpc.accountAbstractionBuildBatchedUserOp.mock.calls;
|
|
911
|
+
expect(typeof calls[0][1]).toBe('string');
|
|
912
|
+
expect(calls[0][1]).toEqual(calls[1][1]);
|
|
913
|
+
}));
|
|
914
|
+
it('should throw if chain is not eip155', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
915
|
+
yield expect(portal.sendBatchedAssets({
|
|
916
|
+
chain: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
917
|
+
transactions: baseRequest.transactions,
|
|
918
|
+
gasReimbursement: {
|
|
919
|
+
feeToken: 'USDC',
|
|
920
|
+
feeRecipient,
|
|
921
|
+
convertGasToFeeAmount: () => '1',
|
|
922
|
+
},
|
|
923
|
+
})).rejects.toThrow('[Portal.sendBatchedAssets] UserOperations are only supported on EIP-155 (EVM) chains');
|
|
924
|
+
}));
|
|
925
|
+
it('should throw if transactions is empty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
926
|
+
yield expect(portal.sendBatchedAssets({
|
|
927
|
+
chain: 'eip155:1',
|
|
928
|
+
transactions: [],
|
|
929
|
+
gasReimbursement: {
|
|
930
|
+
feeToken: 'USDC',
|
|
931
|
+
feeRecipient,
|
|
932
|
+
convertGasToFeeAmount: () => '1',
|
|
933
|
+
},
|
|
934
|
+
})).rejects.toThrow('[Portal.sendBatchedAssets] transactions must contain at least one transaction');
|
|
935
|
+
}));
|
|
936
|
+
it('should throw if convertGasToFeeAmount is missing', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
937
|
+
yield expect(portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: { feeToken: 'USDC', feeRecipient } }))).rejects.toThrow('[Portal.sendBatchedAssets] gasReimbursement.convertGasToFeeAmount (a function) is required');
|
|
938
|
+
}));
|
|
939
|
+
it('should throw if feeRecipient is not a valid EVM address', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
940
|
+
yield expect(portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: {
|
|
941
|
+
feeToken: 'USDC',
|
|
942
|
+
feeRecipient: '0xnope',
|
|
943
|
+
convertGasToFeeAmount: () => '1',
|
|
944
|
+
} }))).rejects.toThrow('[Portal.sendBatchedAssets] Invalid gasReimbursement.feeRecipient');
|
|
945
|
+
}));
|
|
946
|
+
it('should surface an error thrown by the conversion callback', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
947
|
+
const convertGasToFeeAmount = jest
|
|
948
|
+
.fn()
|
|
949
|
+
.mockRejectedValue(new Error('rate unavailable'));
|
|
950
|
+
yield expect(portal.sendBatchedAssets(Object.assign(Object.assign({}, baseRequest), { gasReimbursement: { feeToken: 'USDC', feeRecipient, convertGasToFeeAmount } }))).rejects.toThrow('[Portal.sendBatchedAssets] gasReimbursement.convertGasToFeeAmount threw: rate unavailable');
|
|
951
|
+
}));
|
|
952
|
+
});
|
|
722
953
|
describe('storedClientBackupShare', () => {
|
|
723
954
|
it('should correctly call mpc.storedClientBackupShare', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
724
955
|
yield portal.storedClientBackupShare(true, BackupMethods.password);
|
package/lib/esm/mpc/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { PortalMpcError } from './errors';
|
|
|
11
11
|
import { sdkLogger } from '../logger';
|
|
12
12
|
import { BackupMethods, } from '../index';
|
|
13
13
|
import { generateTraceId } from '../shared/trace';
|
|
14
|
-
const WEB_SDK_VERSION = '3.
|
|
14
|
+
const WEB_SDK_VERSION = '3.17.0-alpha.0';
|
|
15
15
|
class Mpc {
|
|
16
16
|
get ready() {
|
|
17
17
|
return this._ready;
|
|
@@ -226,6 +226,7 @@ class Mpc {
|
|
|
226
226
|
param }, ((options === null || options === void 0 ? void 0 : options.signatureApprovalMemo) !== undefined && {
|
|
227
227
|
signatureApprovalMemo: options.signatureApprovalMemo,
|
|
228
228
|
})),
|
|
229
|
+
traceId: options === null || options === void 0 ? void 0 : options.traceId,
|
|
229
230
|
});
|
|
230
231
|
});
|
|
231
232
|
}
|
|
@@ -913,6 +914,31 @@ class Mpc {
|
|
|
913
914
|
});
|
|
914
915
|
});
|
|
915
916
|
}
|
|
917
|
+
/*******************************
|
|
918
|
+
* Account Abstraction Methods
|
|
919
|
+
*******************************/
|
|
920
|
+
accountAbstractionBuildBatchedUserOp(data, traceId) {
|
|
921
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
922
|
+
return this.handleRequestToIframeAndPost({
|
|
923
|
+
methodMessage: 'portal:accountAbstraction:buildBatchedUserOp',
|
|
924
|
+
errorMessage: 'portal:accountAbstraction:buildBatchedUserOpError',
|
|
925
|
+
resultMessage: 'portal:accountAbstraction:buildBatchedUserOpResult',
|
|
926
|
+
data,
|
|
927
|
+
traceId,
|
|
928
|
+
});
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
accountAbstractionBroadcastBatchedUserOp(data, traceId) {
|
|
932
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
933
|
+
return this.handleRequestToIframeAndPost({
|
|
934
|
+
methodMessage: 'portal:accountAbstraction:broadcastBatchedUserOp',
|
|
935
|
+
errorMessage: 'portal:accountAbstraction:broadcastBatchedUserOpError',
|
|
936
|
+
resultMessage: 'portal:accountAbstraction:broadcastBatchedUserOpResult',
|
|
937
|
+
data,
|
|
938
|
+
traceId,
|
|
939
|
+
});
|
|
940
|
+
});
|
|
941
|
+
}
|
|
916
942
|
/***************************
|
|
917
943
|
* Private Methods
|
|
918
944
|
***************************/
|
|
@@ -12,7 +12,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
12
12
|
};
|
|
13
13
|
import { BackupMethods, MpcStatuses, PortalCurve } from '../index';
|
|
14
14
|
import Mpc from '.';
|
|
15
|
-
import { mockAddress, mockApikey, mockAssets, mockBackupConfig, mockBackupIds, mockBalances, mockBuiltTransaction, mockCipherText, mockClientResponse, mockEjectResult, mockEjectPrivateKeysResult, mockEvaluationResult, mockHost, mockNFTs, mockOrgBackupShares, mockQuoteArgs, mockRpcUrl, mockSharesOnDevice, mockSimulationResult, mockTransactionToEvaluate, mockTransactionToSimulate, mockYieldXyzGetYieldsRequest, mockYieldXyzGetYieldsResponse, mockYieldXyzEnterRequest, mockYieldXyzEnterResponse, mockYieldXyzExitRequest, mockYieldXyzExitResponse, mockYieldXyzGetBalancesRequest, mockYieldXyzGetBalancesResponse, mockYieldXyzGetHistoricalActionsRequest, mockYieldXyzGetHistoricalActionsResponse, mockYieldXyzManageYieldRequest, mockYieldXyzManageYieldResponse, mockYieldXyzTrackTransactionRequest, mockYieldXyzTrackTransactionResponse, mockYieldXyzGetTransactionResponse, mockLifiGetRoutesRequest, mockLifiGetRoutesResponse, mockLifiGetQuoteRequest, mockLifiGetQuoteResponse, mockLifiGetStatusRequest, mockLifiGetStatusResponse, mockLifiGetRouteStepRequest, mockLifiGetRouteStepResponse, mockZeroExQuoteV2Request, mockZeroExQuoteV2Response, mockZeroExSourcesV2Request, mockZeroExSourcesV2Response, mockZeroExPriceRequest, mockZeroExPriceResponse, mockZeroExOptions, mockScanAddressesRequest, mockScanAddressesResponse, mockScanEVMTxRequest, mockScanEVMTxResponse, mockScanEip712TxRequest, mockScanEip712TxResponse, mockScanSolanaTxRequest, mockScanSolanaTxResponse, mockScanNftRequest, mockScanNftResponse, mockScanTokenRequest, mockScanTokenResponse, mockScanUrlRequest, mockScanUrlResponse, mockBlockaidScanEvmTxRequest, mockBlockaidScanEvmTxResponse, mockBlockaidScanSolanaTxRequest, mockBlockaidScanSolanaTxResponse, mockBlockaidScanAddressRequest, mockBlockaidScanAddressResponse, mockBlockaidScanTokensRequest, mockBlockaidScanTokensResponse, mockBlockaidScanUrlRequest, mockBlockaidScanUrlResponse, } from '../__mocks/constants';
|
|
15
|
+
import { mockAddress, mockApikey, mockAssets, mockBackupConfig, mockBackupIds, mockBalances, mockBuiltTransaction, mockCipherText, mockClientResponse, mockEjectResult, mockEjectPrivateKeysResult, mockEvaluationResult, mockHost, mockNFTs, mockOrgBackupShares, mockQuoteArgs, mockRpcUrl, mockSharesOnDevice, mockSimulationResult, mockTransactionToEvaluate, mockTransactionToSimulate, mockYieldXyzGetYieldsRequest, mockYieldXyzGetYieldsResponse, mockYieldXyzEnterRequest, mockYieldXyzEnterResponse, mockYieldXyzExitRequest, mockYieldXyzExitResponse, mockYieldXyzGetBalancesRequest, mockYieldXyzGetBalancesResponse, mockYieldXyzGetHistoricalActionsRequest, mockYieldXyzGetHistoricalActionsResponse, mockYieldXyzManageYieldRequest, mockYieldXyzManageYieldResponse, mockYieldXyzTrackTransactionRequest, mockYieldXyzTrackTransactionResponse, mockYieldXyzGetTransactionResponse, mockLifiGetRoutesRequest, mockLifiGetRoutesResponse, mockLifiGetQuoteRequest, mockLifiGetQuoteResponse, mockLifiGetStatusRequest, mockLifiGetStatusResponse, mockLifiGetRouteStepRequest, mockLifiGetRouteStepResponse, mockZeroExQuoteV2Request, mockZeroExQuoteV2Response, mockZeroExSourcesV2Request, mockZeroExSourcesV2Response, mockZeroExPriceRequest, mockZeroExPriceResponse, mockZeroExOptions, mockScanAddressesRequest, mockScanAddressesResponse, mockScanEVMTxRequest, mockScanEVMTxResponse, mockScanEip712TxRequest, mockScanEip712TxResponse, mockScanSolanaTxRequest, mockScanSolanaTxResponse, mockScanNftRequest, mockScanNftResponse, mockScanTokenRequest, mockScanTokenResponse, mockScanUrlRequest, mockScanUrlResponse, mockBlockaidScanEvmTxRequest, mockBlockaidScanEvmTxResponse, mockBlockaidScanSolanaTxRequest, mockBlockaidScanSolanaTxResponse, mockBlockaidScanAddressRequest, mockBlockaidScanAddressResponse, mockBlockaidScanTokensRequest, mockBlockaidScanTokensResponse, mockBlockaidScanUrlRequest, mockBlockaidScanUrlResponse, mockBuildBatchedUserOpRequest, mockBuildBatchedUserOpResponse, mockBroadcastBatchedUserOpRequest, mockBroadcastBatchedUserOpResponse, } from '../__mocks/constants';
|
|
16
16
|
import portalMock from '../__mocks/portal/portal';
|
|
17
17
|
import { PortalMpcError } from './errors';
|
|
18
18
|
describe('Mpc', () => {
|
|
@@ -3759,4 +3759,138 @@ describe('Mpc', () => {
|
|
|
3759
3759
|
});
|
|
3760
3760
|
});
|
|
3761
3761
|
});
|
|
3762
|
+
describe('accountAbstractionBuildBatchedUserOp', () => {
|
|
3763
|
+
const args = mockBuildBatchedUserOpRequest;
|
|
3764
|
+
const res = mockBuildBatchedUserOpResponse;
|
|
3765
|
+
it('should successfully build a user operation', (done) => {
|
|
3766
|
+
var _a;
|
|
3767
|
+
jest
|
|
3768
|
+
.spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
|
|
3769
|
+
.mockImplementation((message, origin) => {
|
|
3770
|
+
const { type, data } = message;
|
|
3771
|
+
expect(type).toEqual('portal:accountAbstraction:buildBatchedUserOp');
|
|
3772
|
+
expect(data).toMatchObject(args);
|
|
3773
|
+
expect(typeof message.traceId).toBe('string');
|
|
3774
|
+
expect(origin).toEqual(mockHostOrigin);
|
|
3775
|
+
window.dispatchEvent(new MessageEvent('message', {
|
|
3776
|
+
origin: mockHostOrigin,
|
|
3777
|
+
data: {
|
|
3778
|
+
type: 'portal:accountAbstraction:buildBatchedUserOpResult',
|
|
3779
|
+
data: res,
|
|
3780
|
+
},
|
|
3781
|
+
}));
|
|
3782
|
+
});
|
|
3783
|
+
mpc
|
|
3784
|
+
.accountAbstractionBuildBatchedUserOp(args)
|
|
3785
|
+
.then((data) => {
|
|
3786
|
+
expect(data).toEqual(res);
|
|
3787
|
+
done();
|
|
3788
|
+
})
|
|
3789
|
+
.catch((_) => {
|
|
3790
|
+
expect(0).toEqual(1);
|
|
3791
|
+
done();
|
|
3792
|
+
});
|
|
3793
|
+
});
|
|
3794
|
+
it('should error out if the iframe sends an error message', (done) => {
|
|
3795
|
+
var _a;
|
|
3796
|
+
jest
|
|
3797
|
+
.spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
|
|
3798
|
+
.mockImplementationOnce((message, origin) => {
|
|
3799
|
+
const { type, data } = message;
|
|
3800
|
+
expect(type).toEqual('portal:accountAbstraction:buildBatchedUserOp');
|
|
3801
|
+
expect(data).toMatchObject(args);
|
|
3802
|
+
expect(typeof message.traceId).toBe('string');
|
|
3803
|
+
expect(origin).toEqual(mockHostOrigin);
|
|
3804
|
+
window.dispatchEvent(new MessageEvent('message', {
|
|
3805
|
+
origin: mockHostOrigin,
|
|
3806
|
+
data: {
|
|
3807
|
+
type: 'portal:accountAbstraction:buildBatchedUserOpError',
|
|
3808
|
+
data: {
|
|
3809
|
+
code: 1,
|
|
3810
|
+
message: 'test',
|
|
3811
|
+
},
|
|
3812
|
+
},
|
|
3813
|
+
}));
|
|
3814
|
+
});
|
|
3815
|
+
mpc
|
|
3816
|
+
.accountAbstractionBuildBatchedUserOp(args)
|
|
3817
|
+
.then(() => {
|
|
3818
|
+
expect(0).toEqual(1);
|
|
3819
|
+
done();
|
|
3820
|
+
})
|
|
3821
|
+
.catch((e) => {
|
|
3822
|
+
expect(e).toBeInstanceOf(PortalMpcError);
|
|
3823
|
+
expect(e.message).toEqual('test');
|
|
3824
|
+
expect(e.code).toEqual(1);
|
|
3825
|
+
done();
|
|
3826
|
+
});
|
|
3827
|
+
});
|
|
3828
|
+
});
|
|
3829
|
+
describe('accountAbstractionBroadcastBatchedUserOp', () => {
|
|
3830
|
+
const args = mockBroadcastBatchedUserOpRequest;
|
|
3831
|
+
const res = mockBroadcastBatchedUserOpResponse;
|
|
3832
|
+
it('should successfully broadcast a user operation', (done) => {
|
|
3833
|
+
var _a;
|
|
3834
|
+
jest
|
|
3835
|
+
.spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
|
|
3836
|
+
.mockImplementation((message, origin) => {
|
|
3837
|
+
const { type, data } = message;
|
|
3838
|
+
expect(type).toEqual('portal:accountAbstraction:broadcastBatchedUserOp');
|
|
3839
|
+
expect(data).toMatchObject(args);
|
|
3840
|
+
expect(typeof message.traceId).toBe('string');
|
|
3841
|
+
expect(origin).toEqual(mockHostOrigin);
|
|
3842
|
+
window.dispatchEvent(new MessageEvent('message', {
|
|
3843
|
+
origin: mockHostOrigin,
|
|
3844
|
+
data: {
|
|
3845
|
+
type: 'portal:accountAbstraction:broadcastBatchedUserOpResult',
|
|
3846
|
+
data: res,
|
|
3847
|
+
},
|
|
3848
|
+
}));
|
|
3849
|
+
});
|
|
3850
|
+
mpc
|
|
3851
|
+
.accountAbstractionBroadcastBatchedUserOp(args)
|
|
3852
|
+
.then((data) => {
|
|
3853
|
+
expect(data).toEqual(res);
|
|
3854
|
+
done();
|
|
3855
|
+
})
|
|
3856
|
+
.catch((_) => {
|
|
3857
|
+
expect(0).toEqual(1);
|
|
3858
|
+
done();
|
|
3859
|
+
});
|
|
3860
|
+
});
|
|
3861
|
+
it('should error out if the iframe sends an error message', (done) => {
|
|
3862
|
+
var _a;
|
|
3863
|
+
jest
|
|
3864
|
+
.spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
|
|
3865
|
+
.mockImplementationOnce((message, origin) => {
|
|
3866
|
+
const { type, data } = message;
|
|
3867
|
+
expect(type).toEqual('portal:accountAbstraction:broadcastBatchedUserOp');
|
|
3868
|
+
expect(data).toMatchObject(args);
|
|
3869
|
+
expect(typeof message.traceId).toBe('string');
|
|
3870
|
+
expect(origin).toEqual(mockHostOrigin);
|
|
3871
|
+
window.dispatchEvent(new MessageEvent('message', {
|
|
3872
|
+
origin: mockHostOrigin,
|
|
3873
|
+
data: {
|
|
3874
|
+
type: 'portal:accountAbstraction:broadcastBatchedUserOpError',
|
|
3875
|
+
data: {
|
|
3876
|
+
code: 1,
|
|
3877
|
+
message: 'test',
|
|
3878
|
+
},
|
|
3879
|
+
},
|
|
3880
|
+
}));
|
|
3881
|
+
});
|
|
3882
|
+
mpc
|
|
3883
|
+
.accountAbstractionBroadcastBatchedUserOp(args)
|
|
3884
|
+
.then(() => {
|
|
3885
|
+
expect(0).toEqual(1);
|
|
3886
|
+
done();
|
|
3887
|
+
})
|
|
3888
|
+
.catch((e) => {
|
|
3889
|
+
expect(e).toBeInstanceOf(PortalMpcError);
|
|
3890
|
+
expect(e.message).toEqual('test');
|
|
3891
|
+
expect(e.code).toEqual(1);
|
|
3892
|
+
done();
|
|
3893
|
+
});
|
|
3894
|
+
});
|
|
3895
|
+
});
|
|
3762
3896
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Portal MPC Support for Web",
|
|
4
4
|
"author": "Portal Labs, Inc.",
|
|
5
5
|
"homepage": "https://portalhq.io/",
|
|
6
|
-
"version": "3.
|
|
6
|
+
"version": "3.17.0-alpha.0",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"main": "lib/commonjs/index",
|
|
9
9
|
"module": "lib/esm/index",
|
|
@@ -58,5 +58,6 @@
|
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@solana/web3.js": "^1.91.8"
|
|
61
|
-
}
|
|
61
|
+
},
|
|
62
|
+
"stableVersion": "3.16.0-alpha.1"
|
|
62
63
|
}
|
package/src/__mocks/constants.ts
CHANGED
|
@@ -13,9 +13,15 @@ import {
|
|
|
13
13
|
Build7702UpgradeTxResponse,
|
|
14
14
|
BuildAuthorizationListRequest,
|
|
15
15
|
BuildAuthorizationListResponse,
|
|
16
|
+
BuildBatchedUserOpRequest,
|
|
17
|
+
BuildBatchedUserOpResponse,
|
|
18
|
+
BroadcastBatchedUserOpRequest,
|
|
19
|
+
BroadcastBatchedUserOpResponse,
|
|
20
|
+
BuiltEip155Transaction,
|
|
16
21
|
EvmAccountTypeGetStatusRequest,
|
|
17
22
|
EvmAccountTypeGetStatusResponse,
|
|
18
23
|
GetAddressesResponse,
|
|
24
|
+
SendBatchUserOpRequest,
|
|
19
25
|
UpgradeTo7702Request,
|
|
20
26
|
UpgradeTo7702Response,
|
|
21
27
|
} from 'src/shared/types'
|
|
@@ -2085,3 +2091,90 @@ export const mockUpgradeTo7702Request = {
|
|
|
2085
2091
|
export const mockUpgradeTo7702Response = {
|
|
2086
2092
|
txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
2087
2093
|
} as UpgradeTo7702Response
|
|
2094
|
+
|
|
2095
|
+
export const mockBuildBatchedUserOpRequest = {
|
|
2096
|
+
chain: 'eip155:1',
|
|
2097
|
+
calls: [
|
|
2098
|
+
{
|
|
2099
|
+
to: '0xcae0d97d201ad54275b6e8a6b547c7611ad47963',
|
|
2100
|
+
value: '0',
|
|
2101
|
+
data: '0x',
|
|
2102
|
+
},
|
|
2103
|
+
],
|
|
2104
|
+
} as BuildBatchedUserOpRequest
|
|
2105
|
+
|
|
2106
|
+
export const mockBuildBatchedUserOpResponse = {
|
|
2107
|
+
data: {
|
|
2108
|
+
userOperation:
|
|
2109
|
+
'{"sender":"0xabc","nonce":"0x0","initCode":"0x","callData":"0x","callGasLimit":"0x5208","verificationGasLimit":"0x0186A0","preVerificationGas":"0xC350","maxFeePerGas":"0x3B9ACA00","maxPriorityFeePerGas":"0x3B9ACA00","paymasterAndData":"0x","signature":"0x"}',
|
|
2110
|
+
userOpHash:
|
|
2111
|
+
'0xdeadbeef1234567890abcdef1234567890abcdef1234567890abcdef12345678',
|
|
2112
|
+
},
|
|
2113
|
+
metadata: {
|
|
2114
|
+
chainId: 'eip155:1',
|
|
2115
|
+
// Gas info as decimal strings (matching connect-api): totalGas (units),
|
|
2116
|
+
// maxFeePerGas (wei/gas), estimatedGasCostWei = totalGas * maxFeePerGas.
|
|
2117
|
+
totalGas: '100000',
|
|
2118
|
+
maxFeePerGas: '1000000000',
|
|
2119
|
+
estimatedGasCostWei: '100000000000000',
|
|
2120
|
+
},
|
|
2121
|
+
} as BuildBatchedUserOpResponse
|
|
2122
|
+
|
|
2123
|
+
export const mockBroadcastBatchedUserOpRequest = {
|
|
2124
|
+
chain: 'eip155:1',
|
|
2125
|
+
userOperation:
|
|
2126
|
+
'{"sender":"0xabc","nonce":"0x0","initCode":"0x","callData":"0x","callGasLimit":"0x5208","verificationGasLimit":"0x0186A0","preVerificationGas":"0xC350","maxFeePerGas":"0x3B9ACA00","maxPriorityFeePerGas":"0x3B9ACA00","paymasterAndData":"0x","signature":"0x1234"}',
|
|
2127
|
+
signature: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab',
|
|
2128
|
+
} as BroadcastBatchedUserOpRequest
|
|
2129
|
+
|
|
2130
|
+
export const mockBroadcastBatchedUserOpResponse = {
|
|
2131
|
+
data: {
|
|
2132
|
+
userOpHash:
|
|
2133
|
+
'0xfeedface1234567890abcdef1234567890abcdef1234567890abcdef12345678',
|
|
2134
|
+
},
|
|
2135
|
+
metadata: {
|
|
2136
|
+
chainId: 'eip155:1',
|
|
2137
|
+
},
|
|
2138
|
+
} as BroadcastBatchedUserOpResponse
|
|
2139
|
+
|
|
2140
|
+
// ERC-20 token transfer (data contains calldata, no native ETH value)
|
|
2141
|
+
export const mockBuiltEip155Transaction = {
|
|
2142
|
+
transaction: {
|
|
2143
|
+
from: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
2144
|
+
to: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
|
|
2145
|
+
data: '0xa9059cbb000000000000000000000000111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000f4240',
|
|
2146
|
+
},
|
|
2147
|
+
metadata: {
|
|
2148
|
+
amount: '1.0',
|
|
2149
|
+
fromAddress: '0xsender',
|
|
2150
|
+
toAddress: '0xrecipient',
|
|
2151
|
+
tokenAddress: '0xusdc-contract',
|
|
2152
|
+
tokenDecimals: 6,
|
|
2153
|
+
rawAmount: '1000000',
|
|
2154
|
+
},
|
|
2155
|
+
} as BuiltEip155Transaction
|
|
2156
|
+
|
|
2157
|
+
// Native ETH transfer (data is "0x", value comes from rawAmount)
|
|
2158
|
+
export const mockBuiltEip155TransactionNative = {
|
|
2159
|
+
transaction: {
|
|
2160
|
+
from: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
2161
|
+
to: '0x1111111111111111111111111111111111111111',
|
|
2162
|
+
data: '0x',
|
|
2163
|
+
},
|
|
2164
|
+
metadata: {
|
|
2165
|
+
amount: '0.1',
|
|
2166
|
+
fromAddress: '0xsender',
|
|
2167
|
+
toAddress: '0xrecipient',
|
|
2168
|
+
tokenAddress: '0x0000000000000000000000000000000000000000',
|
|
2169
|
+
tokenDecimals: 18,
|
|
2170
|
+
rawAmount: '100000000000000000',
|
|
2171
|
+
},
|
|
2172
|
+
} as BuiltEip155Transaction
|
|
2173
|
+
|
|
2174
|
+
export const mockSendBatchUserOpRequest = {
|
|
2175
|
+
chain: 'eip155:1',
|
|
2176
|
+
transactions: [
|
|
2177
|
+
{ token: 'USDC', value: '1.0', to: '0x1111111111111111111111111111111111111111' },
|
|
2178
|
+
{ token: 'USDC', value: '2.0', to: '0x2222222222222222222222222222222222222222' },
|
|
2179
|
+
],
|
|
2180
|
+
} as SendBatchUserOpRequest
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mockAddress,
|
|
3
|
+
mockBuiltEip155Transaction,
|
|
4
|
+
mockBuildBatchedUserOpResponse,
|
|
5
|
+
mockBroadcastBatchedUserOpResponse,
|
|
3
6
|
mockClientResponse,
|
|
4
7
|
mockEjectResult,
|
|
5
8
|
mockEjectPrivateKeysResult,
|
|
@@ -28,5 +31,13 @@ mpcMock.ejectPrivateKeys = jest
|
|
|
28
31
|
.mockResolvedValue(mockEjectPrivateKeysResult)
|
|
29
32
|
mpcMock.checkSharesOnDevice = jest.fn().mockResolvedValue(mockSharesOnDevice)
|
|
30
33
|
mpcMock.setBackupStatus = jest.fn().mockResolvedValue(true)
|
|
34
|
+
mpcMock.rawSign = jest.fn().mockResolvedValue(mockSignedHash)
|
|
35
|
+
mpcMock.buildTransaction = jest.fn().mockResolvedValue(mockBuiltEip155Transaction)
|
|
36
|
+
mpcMock.accountAbstractionBuildBatchedUserOp = jest
|
|
37
|
+
.fn()
|
|
38
|
+
.mockResolvedValue(mockBuildBatchedUserOpResponse)
|
|
39
|
+
mpcMock.accountAbstractionBroadcastBatchedUserOp = jest
|
|
40
|
+
.fn()
|
|
41
|
+
.mockResolvedValue(mockBroadcastBatchedUserOpResponse)
|
|
31
42
|
|
|
32
43
|
export default mpcMock as jest.Mocked<Mpc>
|