@0xsequence/relayer 2.3.39 → 3.0.0-beta.10

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.
Files changed (83) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +3926 -0
  3. package/LICENSE +0 -17
  4. package/README.md +1 -2
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +3 -0
  8. package/dist/preconditions/codec.d.ts +12 -0
  9. package/dist/preconditions/codec.d.ts.map +1 -0
  10. package/dist/preconditions/codec.js +125 -0
  11. package/dist/preconditions/index.d.ts +4 -0
  12. package/dist/preconditions/index.d.ts.map +1 -0
  13. package/dist/preconditions/index.js +3 -0
  14. package/dist/preconditions/selectors.d.ts +7 -0
  15. package/dist/preconditions/selectors.d.ts.map +1 -0
  16. package/dist/preconditions/selectors.js +27 -0
  17. package/dist/preconditions/types.d.ts +70 -0
  18. package/dist/preconditions/types.d.ts.map +1 -0
  19. package/dist/preconditions/types.js +203 -0
  20. package/dist/relayer/index.d.ts +45 -0
  21. package/dist/relayer/index.d.ts.map +1 -0
  22. package/dist/relayer/index.js +3 -0
  23. package/dist/relayer/relayer.d.ts +26 -0
  24. package/dist/relayer/relayer.d.ts.map +1 -0
  25. package/dist/relayer/relayer.js +7 -0
  26. package/dist/relayer/rpc-relayer/index.d.ts +38 -0
  27. package/dist/relayer/rpc-relayer/index.d.ts.map +1 -0
  28. package/dist/relayer/rpc-relayer/index.js +375 -0
  29. package/dist/{declarations/src → relayer}/rpc-relayer/relayer.gen.d.ts +3 -2
  30. package/dist/relayer/rpc-relayer/relayer.gen.d.ts.map +1 -0
  31. package/dist/relayer/rpc-relayer/relayer.gen.js +1246 -0
  32. package/dist/relayer/standard/abi.d.ts +73 -0
  33. package/dist/relayer/standard/abi.d.ts.map +1 -0
  34. package/dist/relayer/standard/abi.js +10 -0
  35. package/dist/relayer/standard/eip6963.d.ts +31 -0
  36. package/dist/relayer/standard/eip6963.d.ts.map +1 -0
  37. package/dist/relayer/standard/eip6963.js +51 -0
  38. package/dist/relayer/standard/index.d.ts +5 -0
  39. package/dist/relayer/standard/index.d.ts.map +1 -0
  40. package/dist/relayer/standard/index.js +4 -0
  41. package/dist/relayer/standard/local.d.ts +60 -0
  42. package/dist/relayer/standard/local.d.ts.map +1 -0
  43. package/dist/relayer/standard/local.js +285 -0
  44. package/dist/relayer/standard/pk-relayer.d.ts +28 -0
  45. package/dist/relayer/standard/pk-relayer.d.ts.map +1 -0
  46. package/dist/relayer/standard/pk-relayer.js +112 -0
  47. package/dist/relayer/standard/sequence.d.ts +27 -0
  48. package/dist/relayer/standard/sequence.d.ts.map +1 -0
  49. package/dist/relayer/standard/sequence.js +84 -0
  50. package/package.json +28 -25
  51. package/src/index.ts +3 -111
  52. package/src/preconditions/codec.ts +190 -0
  53. package/src/preconditions/index.ts +3 -0
  54. package/src/preconditions/selectors.ts +38 -0
  55. package/src/preconditions/types.ts +201 -0
  56. package/src/relayer/index.ts +60 -0
  57. package/src/relayer/relayer.ts +37 -0
  58. package/src/relayer/rpc-relayer/index.ts +449 -0
  59. package/src/{rpc-relayer → relayer/rpc-relayer}/relayer.gen.ts +483 -258
  60. package/src/relayer/standard/abi.ts +13 -0
  61. package/src/relayer/standard/eip6963.ts +74 -0
  62. package/src/relayer/standard/index.ts +4 -0
  63. package/src/relayer/standard/local.ts +353 -0
  64. package/src/relayer/standard/pk-relayer.ts +138 -0
  65. package/src/relayer/standard/sequence.ts +110 -0
  66. package/test/preconditions/codec.test.ts +531 -0
  67. package/test/preconditions/preconditions.test.ts +283 -0
  68. package/test/preconditions/selectors.test.ts +415 -0
  69. package/test/preconditions/types.test.ts +443 -0
  70. package/test/relayer/relayer.test.ts +355 -0
  71. package/tsconfig.json +10 -0
  72. package/dist/0xsequence-relayer.cjs.d.ts +0 -2
  73. package/dist/0xsequence-relayer.cjs.dev.js +0 -1865
  74. package/dist/0xsequence-relayer.cjs.js +0 -7
  75. package/dist/0xsequence-relayer.cjs.prod.js +0 -1865
  76. package/dist/0xsequence-relayer.esm.js +0 -1852
  77. package/dist/declarations/src/index.d.ts +0 -42
  78. package/dist/declarations/src/local-relayer.d.ts +0 -35
  79. package/dist/declarations/src/provider-relayer.d.ts +0 -47
  80. package/dist/declarations/src/rpc-relayer/index.d.ts +0 -72
  81. package/src/local-relayer.ts +0 -125
  82. package/src/provider-relayer.ts +0 -284
  83. package/src/rpc-relayer/index.ts +0 -380
@@ -0,0 +1,112 @@
1
+ import { Address, Hex, Secp256k1, TransactionEnvelopeEip1559, TransactionReceipt } from 'ox';
2
+ import { LocalRelayer } from './local.js';
3
+ export class PkRelayer {
4
+ provider;
5
+ kind = 'relayer';
6
+ type = 'pk';
7
+ id = 'pk';
8
+ relayer;
9
+ constructor(privateKey, provider) {
10
+ this.provider = provider;
11
+ const relayerAddress = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey }));
12
+ this.relayer = new LocalRelayer({
13
+ sendTransaction: async (args, chainId) => {
14
+ const providerChainId = Number(await this.provider.request({ method: 'eth_chainId' }));
15
+ if (providerChainId !== chainId) {
16
+ throw new Error('Provider chain id does not match relayer chain id');
17
+ }
18
+ const oxArgs = { ...args, to: args.to, data: args.data };
19
+ // Estimate gas with a safety buffer
20
+ const estimatedGas = BigInt(await this.provider.request({ method: 'eth_estimateGas', params: [oxArgs] }));
21
+ const safeGasLimit = estimatedGas > 21000n ? (estimatedGas * 12n) / 10n : 50000n;
22
+ // Get base fee and priority fee
23
+ const baseFee = BigInt(await this.provider.request({ method: 'eth_gasPrice' }));
24
+ const priorityFee = 100000000n; // 0.1 gwei priority fee
25
+ const maxFeePerGas = baseFee + priorityFee;
26
+ // Check sender have enough balance
27
+ const senderBalance = BigInt(await this.provider.request({ method: 'eth_getBalance', params: [relayerAddress, 'latest'] }));
28
+ if (senderBalance < maxFeePerGas * safeGasLimit) {
29
+ console.log('Sender balance:', senderBalance.toString(), 'wei');
30
+ throw new Error('Sender has insufficient balance to pay for gas');
31
+ }
32
+ const nonce = BigInt(await this.provider.request({
33
+ method: 'eth_getTransactionCount',
34
+ params: [relayerAddress, 'latest'],
35
+ }));
36
+ // Build the relay envelope
37
+ const relayEnvelope = TransactionEnvelopeEip1559.from({
38
+ chainId: Number(chainId),
39
+ type: 'eip1559',
40
+ from: relayerAddress,
41
+ to: oxArgs.to,
42
+ data: oxArgs.data,
43
+ gas: safeGasLimit,
44
+ maxFeePerGas: maxFeePerGas,
45
+ maxPriorityFeePerGas: priorityFee,
46
+ nonce: nonce,
47
+ value: 0n,
48
+ });
49
+ const relayerSignature = Secp256k1.sign({
50
+ payload: TransactionEnvelopeEip1559.getSignPayload(relayEnvelope),
51
+ privateKey: privateKey,
52
+ });
53
+ const signedRelayEnvelope = TransactionEnvelopeEip1559.from(relayEnvelope, {
54
+ signature: relayerSignature,
55
+ });
56
+ const tx = await this.provider.request({
57
+ method: 'eth_sendRawTransaction',
58
+ params: [TransactionEnvelopeEip1559.serialize(signedRelayEnvelope)],
59
+ });
60
+ return tx;
61
+ },
62
+ getBalance: async (address) => {
63
+ const balanceHex = await this.provider.request({
64
+ method: 'eth_getBalance',
65
+ params: [address, 'latest'],
66
+ });
67
+ return BigInt(balanceHex);
68
+ },
69
+ call: async (args) => {
70
+ const callArgs = { to: args.to, data: args.data };
71
+ return await this.provider.request({ method: 'eth_call', params: [callArgs, 'latest'] });
72
+ },
73
+ getTransactionReceipt: async (txHash, chainId) => {
74
+ Hex.assert(txHash);
75
+ const providerChainId = Number(await this.provider.request({ method: 'eth_chainId' }));
76
+ if (providerChainId !== chainId) {
77
+ throw new Error('Provider chain id does not match relayer chain id');
78
+ }
79
+ const rpcReceipt = await this.provider.request({ method: 'eth_getTransactionReceipt', params: [txHash] });
80
+ if (!rpcReceipt) {
81
+ return 'unknown';
82
+ }
83
+ const receipt = TransactionReceipt.fromRpc(rpcReceipt);
84
+ return receipt.status === 'success' ? 'success' : 'failed';
85
+ },
86
+ });
87
+ }
88
+ async isAvailable(_wallet, chainId) {
89
+ const providerChainId = Number(await this.provider.request({ method: 'eth_chainId' }));
90
+ return providerChainId === chainId;
91
+ }
92
+ feeTokens() {
93
+ return this.relayer.feeTokens();
94
+ }
95
+ feeOptions(wallet, chainId, calls) {
96
+ return this.relayer.feeOptions(wallet, chainId, calls);
97
+ }
98
+ async relay(to, data, chainId, _) {
99
+ const providerChainId = Number(await this.provider.request({ method: 'eth_chainId' }));
100
+ if (providerChainId !== chainId) {
101
+ throw new Error('Provider chain id does not match relayer chain id');
102
+ }
103
+ return this.relayer.relay(to, data, chainId);
104
+ }
105
+ status(opHash, chainId) {
106
+ return this.relayer.status(opHash, chainId);
107
+ }
108
+ async checkPrecondition(precondition) {
109
+ // TODO: Implement precondition check
110
+ return true;
111
+ }
112
+ }
@@ -0,0 +1,27 @@
1
+ import { TransactionPrecondition, FeeToken } from '../rpc-relayer/relayer.gen.js';
2
+ import { Payload } from '@0xsequence/wallet-primitives';
3
+ import { Address, Hex } from 'ox';
4
+ import { FeeOption, FeeQuote, OperationStatus, Relayer } from '../index.js';
5
+ export declare class SequenceRelayer implements Relayer {
6
+ readonly kind: 'relayer';
7
+ readonly type = "sequence";
8
+ readonly id = "sequence";
9
+ private readonly service;
10
+ constructor(host: string);
11
+ isAvailable(_wallet: Address.Address, _chainId: number): Promise<boolean>;
12
+ feeTokens(): Promise<{
13
+ isFeeRequired: boolean;
14
+ tokens?: FeeToken[];
15
+ paymentAddress?: Address.Address;
16
+ }>;
17
+ feeOptions(wallet: Address.Address, _chainId: number, calls: Payload.Call[]): Promise<{
18
+ options: FeeOption[];
19
+ quote?: FeeQuote;
20
+ }>;
21
+ checkPrecondition(precondition: TransactionPrecondition): Promise<boolean>;
22
+ relay(to: Address.Address, data: Hex.Hex, _chainId: number, quote?: FeeQuote): Promise<{
23
+ opHash: Hex.Hex;
24
+ }>;
25
+ status(opHash: Hex.Hex, _chainId: number): Promise<OperationStatus>;
26
+ }
27
+ //# sourceMappingURL=sequence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../../src/relayer/standard/sequence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,uBAAuB,EAAsB,QAAQ,EAAE,MAAM,+BAA+B,CAAA;AACnH,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AACvD,OAAO,EAAe,OAAO,EAAS,GAAG,EAAE,MAAM,IAAI,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC3E,qBAAa,eAAgB,YAAW,OAAO;IAC7C,SAAgB,IAAI,EAAE,SAAS,CAAY;IAC3C,SAAgB,IAAI,cAAa;IACjC,QAAQ,CAAC,EAAE,cAAa;IAExB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,IAAI,EAAE,MAAM;IAIlB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzE,SAAS,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAC,OAAO,CAAA;KAAE,CAAC;IAgBvG,UAAU,CACd,MAAM,EAAE,OAAO,CAAC,OAAO,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,GACpB,OAAO,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;KAAE,CAAC;IAehD,iBAAiB,CAAC,YAAY,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IAK1E,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAA;KAAE,CAAC;IAW3G,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAuC1E"}
@@ -0,0 +1,84 @@
1
+ import { ETHTxnStatus, Relayer as Service } from '../rpc-relayer/relayer.gen.js';
2
+ import { Payload } from '@0xsequence/wallet-primitives';
3
+ import { AbiFunction, Address, Bytes, Hex } from 'ox';
4
+ export class SequenceRelayer {
5
+ kind = 'relayer';
6
+ type = 'sequence';
7
+ id = 'sequence';
8
+ service;
9
+ constructor(host) {
10
+ this.service = new Service(host, fetch);
11
+ }
12
+ async isAvailable(_wallet, _chainId) {
13
+ return true;
14
+ }
15
+ async feeTokens() {
16
+ const { isFeeRequired, tokens, paymentAddress } = await this.service.feeTokens();
17
+ if (isFeeRequired) {
18
+ Address.assert(paymentAddress);
19
+ return {
20
+ isFeeRequired,
21
+ tokens,
22
+ paymentAddress,
23
+ };
24
+ }
25
+ // Not required
26
+ return {
27
+ isFeeRequired,
28
+ };
29
+ }
30
+ async feeOptions(wallet, _chainId, calls) {
31
+ const to = wallet; // TODO: this might be the guest module
32
+ const execute = AbiFunction.from('function execute(bytes calldata _payload, bytes calldata _signature)');
33
+ const payload = Payload.encode({ type: 'call', space: 0n, nonce: 0n, calls }, to);
34
+ const signature = '0x0001'; // TODO: use a stub signature
35
+ const data = AbiFunction.encodeData(execute, [Bytes.toHex(payload), signature]);
36
+ const { options, quote } = await this.service.feeOptions({ wallet, to, data });
37
+ return {
38
+ options,
39
+ quote: quote ? { _tag: 'FeeQuote', _quote: quote } : undefined,
40
+ };
41
+ }
42
+ async checkPrecondition(precondition) {
43
+ // TODO: implement
44
+ return false;
45
+ }
46
+ async relay(to, data, _chainId, quote) {
47
+ const walletAddress = to; // TODO: pass wallet address or stop requiring it
48
+ const { txnHash } = await this.service.sendMetaTxn({
49
+ call: { walletAddress, contract: to, input: data },
50
+ quote: quote && quote._quote,
51
+ });
52
+ return { opHash: `0x${txnHash}` };
53
+ }
54
+ async status(opHash, _chainId) {
55
+ try {
56
+ const { receipt: { status, revertReason, txnReceipt }, } = await this.service.getMetaTxnReceipt({ metaTxID: opHash });
57
+ switch (status) {
58
+ case ETHTxnStatus.UNKNOWN:
59
+ return { status: 'unknown' };
60
+ case ETHTxnStatus.DROPPED:
61
+ return { status: 'failed', reason: revertReason ?? status };
62
+ case ETHTxnStatus.QUEUED:
63
+ return { status: 'pending' };
64
+ case ETHTxnStatus.SENT:
65
+ return { status: 'pending' };
66
+ case ETHTxnStatus.SUCCEEDED: {
67
+ const receipt = JSON.parse(txnReceipt);
68
+ const transactionHash = receipt.transactionHash;
69
+ Hex.assert(transactionHash);
70
+ return { status: 'confirmed', transactionHash };
71
+ }
72
+ case ETHTxnStatus.PARTIALLY_FAILED:
73
+ return { status: 'failed', reason: revertReason ?? status };
74
+ case ETHTxnStatus.FAILED:
75
+ return { status: 'failed', reason: revertReason ?? status };
76
+ default:
77
+ throw new Error(`unknown transaction status '${status}'`);
78
+ }
79
+ }
80
+ catch {
81
+ return { status: 'pending' };
82
+ }
83
+ }
84
+ }
package/package.json CHANGED
@@ -1,36 +1,39 @@
1
1
  {
2
2
  "name": "@0xsequence/relayer",
3
- "version": "2.3.39",
3
+ "version": "3.0.0-beta.10",
4
+ "type": "module",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
4
8
  "description": "relayer sub-package for Sequence",
5
- "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/relayer",
6
- "source": "src/index.ts",
7
- "main": "dist/0xsequence-relayer.cjs.js",
8
- "module": "dist/0xsequence-relayer.esm.js",
9
- "author": "Horizon Blockchain Games",
9
+ "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/services/relayer",
10
+ "author": "Sequence Platforms Inc.",
10
11
  "license": "Apache-2.0",
11
- "peerDependencies": {
12
- "ethers": ">=6"
13
- },
14
- "dependencies": {
15
- "@0xsequence/abi": "2.3.39",
16
- "@0xsequence/core": "2.3.39",
17
- "@0xsequence/utils": "2.3.39"
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ }
18
17
  },
19
18
  "devDependencies": {
20
- "@0xsequence/wallet-contracts": "^3.0.1",
21
- "ethers": "6.13.4",
22
- "@0xsequence/signhub": "2.3.39",
23
- "@0xsequence/tests": "2.3.39"
19
+ "@types/node": "^25.0.2",
20
+ "typescript": "^5.9.3",
21
+ "vitest": "^4.0.15",
22
+ "@repo/typescript-config": "^0.0.1-beta.1"
23
+ },
24
+ "dependencies": {
25
+ "mipd": "^0.0.7",
26
+ "ox": "^0.9.17",
27
+ "viem": "^2.40.3",
28
+ "@0xsequence/wallet-primitives": "^3.0.0-beta.10"
24
29
  },
25
- "files": [
26
- "src",
27
- "dist"
28
- ],
29
30
  "scripts": {
30
- "test": "pnpm test:concurrently 'pnpm test:run'",
31
- "test:run": "pnpm test:file tests/**/*.spec.ts",
32
- "test:file": "NODE_OPTIONS='--import tsx' mocha --timeout 60000",
33
- "test:concurrently": "concurrently -k --success first 'pnpm start:hardhat > /dev/null' ",
31
+ "build": "tsc",
32
+ "dev": "tsc --watch",
33
+ "old-test": "pnpm test:concurrently 'pnpm test:run'",
34
+ "old-test:run": "pnpm test:file tests/**/*.spec.ts",
35
+ "old-test:file": "NODE_OPTIONS='--import tsx' mocha --timeout 60000",
36
+ "old-test:concurrently": "concurrently -k --success first 'pnpm start:hardhat > /dev/null' ",
34
37
  "start:hardhat": "pnpm hardhat node --port 9547",
35
38
  "typecheck": "tsc --noEmit"
36
39
  }
package/src/index.ts CHANGED
@@ -1,111 +1,3 @@
1
- import { ethers } from 'ethers'
2
- import { proto } from './rpc-relayer'
3
-
4
- import { commons } from '@0xsequence/core'
5
-
6
- export interface Relayer {
7
- // simulate returns the execution results for a list of transactions.
8
- simulate(wallet: string, ...transactions: commons.transaction.Transaction[]): Promise<SimulateResult[]>
9
-
10
- // getFeeOptions returns the fee options that the relayer will accept as payment.
11
- // If a quote is returned, it may be passed back to the relayer for dispatch.
12
- getFeeOptions(
13
- address: string,
14
- ...transactions: commons.transaction.Transaction[]
15
- ): Promise<{ options: FeeOption[]; quote?: FeeQuote }>
16
-
17
- // getFeeOptionsRaw returns the fee options that the relayer will accept as payment.
18
- // If a quote is returned, it may be passed back to the relayer for dispatch.
19
- // It doesn't make any assumptions about the transaction format.
20
- getFeeOptionsRaw(
21
- entrypoint: string,
22
- data: ethers.BytesLike,
23
- options?: {
24
- simulate?: boolean
25
- }
26
- ): Promise<{ options: FeeOption[]; quote?: FeeQuote }>
27
-
28
- // gasRefundOptions returns the transactions which can be included to refund a
29
- // relayer for submitting your transaction to a network.
30
- gasRefundOptions(address: string, ...transactions: commons.transaction.Transaction[]): Promise<FeeOption[]>
31
-
32
- // Gas tank sponsorship management
33
- listGasSponsors(args: proto.ListGasSponsorsArgs): Promise<proto.ListGasSponsorsReturn>
34
- addGasSponsor(args: proto.AddGasSponsorArgs): Promise<proto.AddGasSponsorReturn>
35
- updateGasSponsor(args: proto.UpdateGasSponsorArgs): Promise<proto.UpdateGasSponsorReturn>
36
- removeGasSponsor(args: proto.RemoveGasSponsorArgs): Promise<proto.RemoveGasSponsorReturn>
37
-
38
- // getNonce returns the transaction count/nonce for a wallet, encoded with nonce space.
39
- // If space is undefined, the relayer can choose a nonce space to encode the result with.
40
- // Otherwise, the relayer must return a nonce encoded for the given nonce space.
41
- getNonce(address: string, space?: ethers.BigNumberish, blockTag?: ethers.BlockTag): Promise<ethers.BigNumberish>
42
-
43
- // relayer will submit the transaction(s) to the network and return the transaction response.
44
- // The quote should be the one returned from getFeeOptions, if any.
45
- // waitForReceipt must default to true.
46
- relay(
47
- signedTxs: commons.transaction.IntendedTransactionBundle,
48
- quote?: FeeQuote,
49
- waitForReceipt?: boolean,
50
- projectAccessKey?: string
51
- ): Promise<commons.transaction.TransactionResponse>
52
-
53
- // wait for transaction confirmation
54
- // timeout is the maximum time to wait for the transaction response
55
- // delay is the polling interval, i.e. the time to wait between requests
56
- // maxFails is the maximum number of hard failures to tolerate before giving up
57
- wait(
58
- metaTxnId: string | commons.transaction.SignedTransactionBundle,
59
- timeout?: number,
60
- delay?: number,
61
- maxFails?: number
62
- ): Promise<commons.transaction.TransactionResponse>
63
-
64
- // getMetaTransactions returns a list of meta transactions for a given project and gas tank
65
- getMetaTransactions(
66
- projectId: number,
67
- page?: proto.Page
68
- ): Promise<{
69
- page: proto.Page
70
- transactions: proto.MetaTxnLog[]
71
- }>
72
-
73
- // getTransactionCost returns the used fee cost for gas tank during a given period
74
- getTransactionCost(
75
- projectId: number,
76
- from: string,
77
- to: string
78
- ): Promise<{
79
- cost: number
80
- }>
81
- }
82
-
83
- export * from './local-relayer'
84
- export * from './provider-relayer'
85
- export * from './rpc-relayer'
86
- export { proto as RpcRelayerProto } from './rpc-relayer'
87
- export type SimulateResult = proto.SimulateResult
88
- export type FeeOption = proto.FeeOption
89
-
90
- // A fee quote is simply an opaque value that can be obtained via Relayer.getFeeOptions(), and
91
- // returned back to the same relayer via Relayer.relay(). Fee quotes should be treated as an
92
- // implementation detail of the relayer that produces them.
93
- //
94
- // This interface exists for type-safety purposes to protect against passing non-FeeQuotes to
95
- // Relayer.relay(), or any other functions that call it indirectly (e.g. Account.sendTransaction).
96
- export interface FeeQuote {
97
- _tag: 'FeeQuote'
98
- _quote: unknown
99
- }
100
-
101
- export function isRelayer(cand: any): cand is Relayer {
102
- return (
103
- typeof cand === 'object' &&
104
- typeof cand.simulate === 'function' &&
105
- typeof cand.getFeeOptions === 'function' &&
106
- typeof cand.gasRefundOptions === 'function' &&
107
- typeof cand.getNonce === 'function' &&
108
- typeof cand.relay === 'function' &&
109
- typeof cand.wait === 'function'
110
- )
111
- }
1
+ export * as Relayer from './relayer/index.js'
2
+ export * as RpcRelayerGen from './relayer/rpc-relayer/relayer.gen.js'
3
+ export * as Preconditions from './preconditions/index.js'
@@ -0,0 +1,190 @@
1
+ import { Address } from 'ox'
2
+ import {
3
+ Precondition,
4
+ NativeBalancePrecondition,
5
+ Erc20BalancePrecondition,
6
+ Erc20ApprovalPrecondition,
7
+ Erc721OwnershipPrecondition,
8
+ Erc721ApprovalPrecondition,
9
+ Erc1155BalancePrecondition,
10
+ Erc1155ApprovalPrecondition,
11
+ } from './types.js'
12
+
13
+ export interface TransactionPrecondition {
14
+ type: string
15
+ chainId: number
16
+ ownerAddress: string
17
+ tokenAddress: string
18
+ minAmount: bigint
19
+ }
20
+
21
+ export function decodePreconditions(preconditions: TransactionPrecondition[]): Precondition[] {
22
+ const decodedPreconditions: Precondition[] = []
23
+
24
+ for (const p of preconditions) {
25
+ const decoded = decodePrecondition(p)
26
+ if (decoded) {
27
+ decodedPreconditions.push(decoded)
28
+ }
29
+ }
30
+
31
+ return decodedPreconditions
32
+ }
33
+
34
+ export function decodePrecondition(p: TransactionPrecondition): Precondition | undefined {
35
+ if (!p) {
36
+ return undefined
37
+ }
38
+
39
+ let precondition: Precondition | undefined
40
+
41
+ try {
42
+ switch (p.type) {
43
+ case 'native-balance':
44
+ precondition = new NativeBalancePrecondition(Address.from(p.ownerAddress), p.minAmount, undefined)
45
+ break
46
+
47
+ case 'erc20-balance':
48
+ precondition = new Erc20BalancePrecondition(
49
+ Address.from(p.ownerAddress),
50
+ Address.from(p.tokenAddress),
51
+ p.minAmount,
52
+ undefined,
53
+ )
54
+ break
55
+
56
+ case 'erc20-approval':
57
+ precondition = new Erc20ApprovalPrecondition(
58
+ Address.from(p.ownerAddress),
59
+ Address.from(p.tokenAddress),
60
+ Address.from(p.ownerAddress),
61
+ p.minAmount,
62
+ )
63
+ break
64
+
65
+ case 'erc721-ownership':
66
+ precondition = new Erc721OwnershipPrecondition(
67
+ Address.from(p.ownerAddress),
68
+ Address.from(p.tokenAddress),
69
+ BigInt(0),
70
+ true,
71
+ )
72
+ break
73
+
74
+ case 'erc721-approval':
75
+ precondition = new Erc721ApprovalPrecondition(
76
+ Address.from(p.ownerAddress),
77
+ Address.from(p.tokenAddress),
78
+ BigInt(0),
79
+ Address.from(p.ownerAddress),
80
+ )
81
+ break
82
+
83
+ case 'erc1155-balance':
84
+ precondition = new Erc1155BalancePrecondition(
85
+ Address.from(p.ownerAddress),
86
+ Address.from(p.tokenAddress),
87
+ BigInt(0),
88
+ p.minAmount,
89
+ undefined,
90
+ )
91
+ break
92
+
93
+ case 'erc1155-approval':
94
+ precondition = new Erc1155ApprovalPrecondition(
95
+ Address.from(p.ownerAddress),
96
+ Address.from(p.tokenAddress),
97
+ BigInt(0),
98
+ Address.from(p.ownerAddress),
99
+ p.minAmount,
100
+ )
101
+ break
102
+
103
+ default:
104
+ return undefined
105
+ }
106
+
107
+ const error = precondition.isValid()
108
+ if (error) {
109
+ console.warn(`Invalid precondition: ${error.message}`)
110
+ return undefined
111
+ }
112
+
113
+ return precondition
114
+ } catch (e) {
115
+ console.warn(`Failed to decode precondition: ${e}`)
116
+ return undefined
117
+ }
118
+ }
119
+
120
+ export function encodePrecondition(p: Precondition): string {
121
+ const data: any = {}
122
+
123
+ switch (p.type()) {
124
+ case 'native-balance': {
125
+ const native = p as NativeBalancePrecondition
126
+ data.address = native.address.toString()
127
+ if (native.min !== undefined) data.min = native.min.toString()
128
+ if (native.max !== undefined) data.max = native.max.toString()
129
+ break
130
+ }
131
+
132
+ case 'erc20-balance': {
133
+ const erc20 = p as Erc20BalancePrecondition
134
+ data.address = erc20.address.toString()
135
+ data.token = erc20.token.toString()
136
+ if (erc20.min !== undefined) data.min = erc20.min.toString()
137
+ if (erc20.max !== undefined) data.max = erc20.max.toString()
138
+ break
139
+ }
140
+
141
+ case 'erc20-approval': {
142
+ const erc20 = p as Erc20ApprovalPrecondition
143
+ data.address = erc20.address.toString()
144
+ data.token = erc20.token.toString()
145
+ data.operator = erc20.operator.toString()
146
+ data.min = erc20.min.toString()
147
+ break
148
+ }
149
+
150
+ case 'erc721-ownership': {
151
+ const erc721 = p as Erc721OwnershipPrecondition
152
+ data.address = erc721.address.toString()
153
+ data.token = erc721.token.toString()
154
+ data.tokenId = erc721.tokenId.toString()
155
+ if (erc721.owned !== undefined) data.owned = erc721.owned
156
+ break
157
+ }
158
+
159
+ case 'erc721-approval': {
160
+ const erc721 = p as Erc721ApprovalPrecondition
161
+ data.address = erc721.address.toString()
162
+ data.token = erc721.token.toString()
163
+ data.tokenId = erc721.tokenId.toString()
164
+ data.operator = erc721.operator.toString()
165
+ break
166
+ }
167
+
168
+ case 'erc1155-balance': {
169
+ const erc1155 = p as Erc1155BalancePrecondition
170
+ data.address = erc1155.address.toString()
171
+ data.token = erc1155.token.toString()
172
+ data.tokenId = erc1155.tokenId.toString()
173
+ if (erc1155.min !== undefined) data.min = erc1155.min.toString()
174
+ if (erc1155.max !== undefined) data.max = erc1155.max.toString()
175
+ break
176
+ }
177
+
178
+ case 'erc1155-approval': {
179
+ const erc1155 = p as Erc1155ApprovalPrecondition
180
+ data.address = erc1155.address.toString()
181
+ data.token = erc1155.token.toString()
182
+ data.tokenId = erc1155.tokenId.toString()
183
+ data.operator = erc1155.operator.toString()
184
+ data.min = erc1155.min.toString()
185
+ break
186
+ }
187
+ }
188
+
189
+ return JSON.stringify(data)
190
+ }
@@ -0,0 +1,3 @@
1
+ export * from './types.js'
2
+ export * from './codec.js'
3
+ export * from './selectors.js'
@@ -0,0 +1,38 @@
1
+ import { Precondition, NativeBalancePrecondition, Erc20BalancePrecondition } from './types.js'
2
+ import { TransactionPrecondition, decodePreconditions } from './codec.js'
3
+
4
+ export function extractChainID(precondition: TransactionPrecondition): number | undefined {
5
+ if (!precondition) {
6
+ return undefined
7
+ }
8
+
9
+ return precondition.chainId
10
+ }
11
+
12
+ export function extractSupportedPreconditions(preconditions: TransactionPrecondition[]): Precondition[] {
13
+ if (!preconditions || preconditions.length === 0) {
14
+ return []
15
+ }
16
+
17
+ return decodePreconditions(preconditions)
18
+ }
19
+
20
+ export function extractNativeBalancePreconditions(
21
+ preconditions: TransactionPrecondition[],
22
+ ): NativeBalancePrecondition[] {
23
+ if (!preconditions || preconditions.length === 0) {
24
+ return []
25
+ }
26
+
27
+ const decoded = decodePreconditions(preconditions)
28
+ return decoded.filter((p): p is NativeBalancePrecondition => p.type() === 'native-balance')
29
+ }
30
+
31
+ export function extractERC20BalancePreconditions(preconditions: TransactionPrecondition[]): Erc20BalancePrecondition[] {
32
+ if (!preconditions || preconditions.length === 0) {
33
+ return []
34
+ }
35
+
36
+ const decoded = decodePreconditions(preconditions)
37
+ return decoded.filter((p): p is Erc20BalancePrecondition => p.type() === 'erc20-balance')
38
+ }