@chainlink/ccip-sdk 1.1.0 → 1.2.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/dist/api/index.d.ts +165 -15
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +236 -61
- package/dist/api/index.js.map +1 -1
- package/dist/api/types.d.ts +119 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +5 -5
- package/dist/aptos/index.js.map +1 -1
- package/dist/chain.d.ts +65 -24
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +84 -11
- package/dist/chain.js.map +1 -1
- package/dist/errors/codes.d.ts +1 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +1 -0
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/recovery.d.ts.map +1 -1
- package/dist/errors/recovery.js +1 -0
- package/dist/errors/recovery.js.map +1 -1
- package/dist/errors/specialized.d.ts +21 -0
- package/dist/errors/specialized.d.ts.map +1 -1
- package/dist/errors/specialized.js +31 -1
- package/dist/errors/specialized.js.map +1 -1
- package/dist/evm/abi/OffRamp_2_0.d.ts +18 -17
- package/dist/evm/abi/OffRamp_2_0.d.ts.map +1 -1
- package/dist/evm/abi/OffRamp_2_0.js +19 -21
- package/dist/evm/abi/OffRamp_2_0.js.map +1 -1
- package/dist/evm/abi/TokenPool_2_0.d.ts +0 -4
- package/dist/evm/abi/TokenPool_2_0.d.ts.map +1 -1
- package/dist/evm/abi/TokenPool_2_0.js +0 -1
- package/dist/evm/abi/TokenPool_2_0.js.map +1 -1
- package/dist/evm/gas.d.ts +14 -4
- package/dist/evm/gas.d.ts.map +1 -1
- package/dist/evm/gas.js +7 -6
- package/dist/evm/gas.js.map +1 -1
- package/dist/evm/index.d.ts +39 -8
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +106 -36
- package/dist/evm/index.js.map +1 -1
- package/dist/extra-args.d.ts +18 -8
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +6 -6
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +1 -1
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +7 -2
- package/dist/gas.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/requests.d.ts +11 -5
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +4 -7
- package/dist/requests.js.map +1 -1
- package/dist/solana/index.d.ts +2 -2
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +3 -2
- package/dist/solana/index.js.map +1 -1
- package/dist/solana/utils.js +2 -2
- package/dist/solana/utils.js.map +1 -1
- package/dist/sui/exec.d.ts +30 -0
- package/dist/sui/exec.d.ts.map +1 -0
- package/dist/sui/exec.js +92 -0
- package/dist/sui/exec.js.map +1 -0
- package/dist/sui/index.d.ts +7 -2
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +23 -65
- package/dist/sui/index.js.map +1 -1
- package/dist/sui/manuallyExec/index.d.ts.map +1 -1
- package/dist/sui/manuallyExec/index.js +10 -13
- package/dist/sui/manuallyExec/index.js.map +1 -1
- package/dist/sui/objects.d.ts.map +1 -1
- package/dist/sui/objects.js +4 -2
- package/dist/sui/objects.js.map +1 -1
- package/dist/sui/types.d.ts +9 -1
- package/dist/sui/types.d.ts.map +1 -1
- package/dist/sui/types.js.map +1 -1
- package/dist/ton/index.d.ts.map +1 -1
- package/dist/ton/index.js +34 -26
- package/dist/ton/index.js.map +1 -1
- package/dist/utils.d.ts +10 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +10 -4
- package/dist/utils.js.map +1 -1
- package/package.json +7 -7
- package/src/api/index.ts +271 -59
- package/src/api/types.ts +126 -1
- package/src/aptos/index.ts +7 -9
- package/src/chain.ts +136 -38
- package/src/errors/codes.ts +1 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recovery.ts +2 -0
- package/src/errors/specialized.ts +33 -1
- package/src/evm/abi/OffRamp_2_0.ts +19 -21
- package/src/evm/abi/TokenPool_2_0.ts +0 -1
- package/src/evm/gas.ts +18 -20
- package/src/evm/index.ts +126 -34
- package/src/extra-args.ts +18 -8
- package/src/gas.ts +8 -3
- package/src/index.ts +5 -0
- package/src/requests.ts +18 -12
- package/src/solana/index.ts +3 -2
- package/src/solana/utils.ts +2 -2
- package/src/sui/exec.ts +131 -0
- package/src/sui/index.ts +33 -98
- package/src/sui/manuallyExec/index.ts +11 -17
- package/src/sui/objects.ts +4 -2
- package/src/sui/types.ts +10 -1
- package/src/ton/index.ts +47 -26
- package/src/utils.ts +10 -4
package/src/sui/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { bcs } from '@mysten/sui/bcs'
|
|
2
|
-
import {
|
|
2
|
+
import { SuiClient } from '@mysten/sui/client'
|
|
3
3
|
import type { Keypair } from '@mysten/sui/cryptography'
|
|
4
4
|
import { SuiGraphQLClient } from '@mysten/sui/graphql'
|
|
5
5
|
import { Transaction } from '@mysten/sui/transactions'
|
|
@@ -17,20 +17,13 @@ import {
|
|
|
17
17
|
import { getCcipStateAddress, getOffRampForCcip } from './discovery.ts'
|
|
18
18
|
import { type CommitEvent, streamSuiLogs } from './events.ts'
|
|
19
19
|
import { getSuiLeafHasher } from './hasher.ts'
|
|
20
|
-
import {
|
|
21
|
-
deriveObjectID,
|
|
22
|
-
fetchTokenConfigs,
|
|
23
|
-
getLatestPackageId,
|
|
24
|
-
getObjectRef,
|
|
25
|
-
getReceiverModule,
|
|
26
|
-
} from './objects.ts'
|
|
20
|
+
import { deriveObjectID, getLatestPackageId, getObjectRef } from './objects.ts'
|
|
27
21
|
import {
|
|
28
22
|
CCIPArgumentInvalidError,
|
|
29
23
|
CCIPContractNotRouterError,
|
|
30
24
|
CCIPDataFormatUnsupportedError,
|
|
31
25
|
CCIPError,
|
|
32
26
|
CCIPErrorCode,
|
|
33
|
-
CCIPExecTxRevertedError,
|
|
34
27
|
CCIPExecutionReportChainMismatchError,
|
|
35
28
|
CCIPLogsAddressRequiredError,
|
|
36
29
|
CCIPNotImplementedError,
|
|
@@ -47,7 +40,6 @@ import {
|
|
|
47
40
|
type CCIPExecution,
|
|
48
41
|
type CCIPMessage,
|
|
49
42
|
type CCIPRequest,
|
|
50
|
-
type CCIPVersion,
|
|
51
43
|
type ChainLog,
|
|
52
44
|
type ChainTransaction,
|
|
53
45
|
type CommitReport,
|
|
@@ -67,12 +59,9 @@ import {
|
|
|
67
59
|
parseTypeAndVersion,
|
|
68
60
|
util,
|
|
69
61
|
} from '../utils.ts'
|
|
70
|
-
import {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
buildManualExecutionPTB,
|
|
74
|
-
} from './manuallyExec/index.ts'
|
|
75
|
-
import type { CCIPMessage_V1_6_Sui } from './types.ts'
|
|
62
|
+
import { generateUnsignedExecutePTB, signAndExecuteSuiTx } from './exec.ts'
|
|
63
|
+
import type { CCIPMessage_V1_6_Sui, UnsignedSuiTx } from './types.ts'
|
|
64
|
+
export type { UnsignedSuiTx }
|
|
76
65
|
|
|
77
66
|
const DEFAULT_GAS_LIMIT = 1000000n
|
|
78
67
|
|
|
@@ -728,11 +717,28 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
728
717
|
return Promise.reject(new CCIPNotImplementedError('SuiChain.sendMessage'))
|
|
729
718
|
}
|
|
730
719
|
|
|
731
|
-
/**
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
720
|
+
/**
|
|
721
|
+
* {@inheritDoc Chain.generateUnsignedExecute}
|
|
722
|
+
* @throws {@link CCIPExecutionReportChainMismatchError} if input is not a Sui v1.6 execution report
|
|
723
|
+
*/
|
|
724
|
+
override async generateUnsignedExecute(
|
|
725
|
+
opts: Parameters<Chain['generateUnsignedExecute']>[0],
|
|
726
|
+
): Promise<UnsignedSuiTx> {
|
|
727
|
+
const resolved = await this.resolveExecuteOpts(opts)
|
|
728
|
+
if (!resolved.offRamp.includes('::')) resolved.offRamp += '::offramp'
|
|
729
|
+
if (!('message' in resolved.input)) {
|
|
730
|
+
throw new CCIPExecutionReportChainMismatchError('Sui')
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
return generateUnsignedExecutePTB(
|
|
734
|
+
this.client,
|
|
735
|
+
resolved.offRamp,
|
|
736
|
+
resolved.input as ExecutionInput<CCIPMessage_V1_6_Sui>,
|
|
737
|
+
{
|
|
738
|
+
gasLimit: resolved.gasLimit,
|
|
739
|
+
receiverObjectIds: (resolved as { receiverObjectIds?: string[] }).receiverObjectIds,
|
|
740
|
+
},
|
|
741
|
+
)
|
|
736
742
|
}
|
|
737
743
|
|
|
738
744
|
/**
|
|
@@ -745,94 +751,23 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
745
751
|
receiverObjectIds?: string[]
|
|
746
752
|
},
|
|
747
753
|
): Promise<CCIPExecution> {
|
|
748
|
-
if (!('input' in opts && 'message' in opts.input)) {
|
|
749
|
-
throw new CCIPExecutionReportChainMismatchError('Sui')
|
|
750
|
-
}
|
|
751
|
-
const { input, offRamp } = opts
|
|
752
754
|
const wallet = opts.wallet as Keypair
|
|
753
755
|
|
|
754
|
-
// Discover the CCIP package from the offramp
|
|
755
|
-
const ccip = await getCcipStateAddress(offRamp, this.client)
|
|
756
|
-
|
|
757
|
-
const ccipObjectRef = await getObjectRef(ccip, this.client)
|
|
758
|
-
const offrampStateObject = await getObjectRef(offRamp, this.client)
|
|
759
|
-
const receiverConfig = await getReceiverModule(
|
|
760
|
-
this.client,
|
|
761
|
-
ccip,
|
|
762
|
-
ccipObjectRef,
|
|
763
|
-
input.message.receiver,
|
|
764
|
-
)
|
|
765
|
-
let tokenConfigs: TokenConfig[] = []
|
|
766
|
-
if (input.message.tokenAmounts.length !== 0) {
|
|
767
|
-
tokenConfigs = await fetchTokenConfigs(
|
|
768
|
-
this.client,
|
|
769
|
-
ccip,
|
|
770
|
-
ccipObjectRef,
|
|
771
|
-
input.message.tokenAmounts as CCIPMessage<typeof CCIPVersion.V1_6>['tokenAmounts'],
|
|
772
|
-
)
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
const suiInput: SuiManuallyExecuteInput = {
|
|
776
|
-
executionReport: input as ExecutionInput<CCIPMessage_V1_6_Sui>,
|
|
777
|
-
offrampAddress: offRamp,
|
|
778
|
-
ccipAddress: ccip,
|
|
779
|
-
ccipObjectRef,
|
|
780
|
-
offrampStateObject,
|
|
781
|
-
receiverConfig,
|
|
782
|
-
tokenConfigs,
|
|
783
|
-
}
|
|
784
756
|
if (opts.receiverObjectIds) {
|
|
785
757
|
this.logger.info(
|
|
786
758
|
`Overriding Sui Manual Execution receiverObjectIds with: ${opts.receiverObjectIds.join(', ')}`,
|
|
787
759
|
)
|
|
788
|
-
suiInput.overrideReceiverObjectIds = opts.receiverObjectIds
|
|
789
760
|
}
|
|
790
|
-
const tx = buildManualExecutionPTB(suiInput)
|
|
791
761
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
this.logger.info(`Executing Sui CCIP execute transaction...`)
|
|
798
|
-
// Sign and execute the transaction
|
|
799
|
-
let result: SuiTransactionBlockResponse
|
|
800
|
-
try {
|
|
801
|
-
result = await this.client.signAndExecuteTransaction({
|
|
802
|
-
signer: wallet,
|
|
803
|
-
transaction: tx,
|
|
804
|
-
options: {
|
|
805
|
-
showEffects: true,
|
|
806
|
-
showEvents: true,
|
|
807
|
-
},
|
|
808
|
-
})
|
|
809
|
-
} catch (e) {
|
|
810
|
-
throw new CCIPError(
|
|
811
|
-
CCIPErrorCode.TRANSACTION_NOT_FINALIZED,
|
|
812
|
-
`Failed to send Sui execute transaction: ${(e as Error).message}`,
|
|
813
|
-
)
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// Check if transaction inmediately reverted
|
|
817
|
-
if (result.effects?.status.status !== 'success') {
|
|
818
|
-
const errorMsg = result.effects?.status.error || 'Unknown error'
|
|
819
|
-
throw new CCIPExecTxRevertedError(result.digest, {
|
|
820
|
-
context: { error: errorMsg },
|
|
821
|
-
})
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
this.logger.info(`Waiting for Sui transaction ${result.digest} to be finalized...`)
|
|
825
|
-
|
|
826
|
-
await this.client.waitForTransaction({
|
|
827
|
-
digest: result.digest,
|
|
828
|
-
options: {
|
|
829
|
-
showEffects: true,
|
|
830
|
-
showEvents: true,
|
|
831
|
-
},
|
|
762
|
+
const unsignedTx = await this.generateUnsignedExecute({
|
|
763
|
+
...opts,
|
|
764
|
+
payer: '',
|
|
832
765
|
})
|
|
833
766
|
|
|
767
|
+
const digest = await signAndExecuteSuiTx(this.client, wallet, unsignedTx, this.logger)
|
|
768
|
+
|
|
834
769
|
// Return the transaction as a ChainTransaction
|
|
835
|
-
return this.getExecutionReceiptInTx(await this.getTransaction(
|
|
770
|
+
return this.getExecutionReceiptInTx(await this.getTransaction(digest))
|
|
836
771
|
}
|
|
837
772
|
|
|
838
773
|
/**
|
|
@@ -4,9 +4,7 @@ import { Transaction } from '@mysten/sui/transactions'
|
|
|
4
4
|
|
|
5
5
|
import { serializeExecutionReport } from './encoder.ts'
|
|
6
6
|
import { CCIPMessageInvalidError } from '../../errors/specialized.ts'
|
|
7
|
-
import { decodeExtraArgs } from '../../extra-args.ts'
|
|
8
7
|
import type { ExecutionInput } from '../../types.ts'
|
|
9
|
-
import { networkInfo } from '../../utils.ts'
|
|
10
8
|
import type { CCIPMessage_V1_6_Sui } from '../types.ts'
|
|
11
9
|
|
|
12
10
|
/** Configuration for manually executing a Sui receiver module. */
|
|
@@ -56,12 +54,16 @@ export function buildManualExecutionPTB({
|
|
|
56
54
|
}: SuiManuallyExecuteInput): Transaction {
|
|
57
55
|
const reportBytes = serializeExecutionReport(executionReport)
|
|
58
56
|
|
|
57
|
+
// Strip any ::module suffixes to get bare package IDs for move call targets
|
|
58
|
+
const offrampPackageId = offrampAddress.split('::')[0]!
|
|
59
|
+
const ccipPackageId = ccipAddress.split('::')[0]!
|
|
60
|
+
|
|
59
61
|
// Create transaction
|
|
60
62
|
const tx = new Transaction()
|
|
61
63
|
|
|
62
64
|
// Step 1: Call manually_init_execute to prepare the execution
|
|
63
65
|
const receiverParamsArg = tx.moveCall({
|
|
64
|
-
target: `${
|
|
66
|
+
target: `${offrampPackageId}::offramp::manually_init_execute`,
|
|
65
67
|
arguments: [
|
|
66
68
|
tx.object(ccipObjectRef),
|
|
67
69
|
tx.object(offrampStateObject),
|
|
@@ -72,7 +74,7 @@ export function buildManualExecutionPTB({
|
|
|
72
74
|
|
|
73
75
|
// Get the message from the from the report using the offramp helper
|
|
74
76
|
const messageArg = tx.moveCall({
|
|
75
|
-
target: `${
|
|
77
|
+
target: `${ccipPackageId}::offramp_state_helper::extract_any2sui_message`,
|
|
76
78
|
arguments: [receiverParamsArg],
|
|
77
79
|
})
|
|
78
80
|
|
|
@@ -96,17 +98,9 @@ export function buildManualExecutionPTB({
|
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
|
|
100
|
-
const decodedExtraArgs = decodeExtraArgs(
|
|
101
|
-
executionReport.message.extraArgs,
|
|
102
|
-
networkInfo(executionReport.message.destChainSelector).family,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
if (!decodedExtraArgs || decodedExtraArgs._tag !== 'SuiExtraArgsV1') {
|
|
106
|
-
throw new CCIPMessageInvalidError('Expected Sui extra args')
|
|
107
|
-
}
|
|
101
|
+
const { receiverObjectIds } = executionReport.message
|
|
108
102
|
|
|
109
|
-
if (
|
|
103
|
+
if (receiverObjectIds.length === 0) {
|
|
110
104
|
throw new CCIPMessageInvalidError('No receiverObjectIds provided in SUIExtraArgsV1')
|
|
111
105
|
}
|
|
112
106
|
// Call the receiver contract
|
|
@@ -116,16 +110,16 @@ export function buildManualExecutionPTB({
|
|
|
116
110
|
tx.pure.vector('u8', Buffer.from(executionReport.message.messageId.slice(2), 'hex')),
|
|
117
111
|
tx.object(ccipObjectRef),
|
|
118
112
|
messageArg,
|
|
119
|
-
// if overrideReceiverObjectIds is provided, use them; otherwise, use the ones from
|
|
113
|
+
// if overrideReceiverObjectIds is provided, use them; otherwise, use the ones from the message
|
|
120
114
|
...(overrideReceiverObjectIds && overrideReceiverObjectIds.length > 0
|
|
121
115
|
? overrideReceiverObjectIds.map(tx.object)
|
|
122
|
-
:
|
|
116
|
+
: receiverObjectIds.map(tx.object)),
|
|
123
117
|
],
|
|
124
118
|
})
|
|
125
119
|
|
|
126
120
|
// Step 2: Call finish_execute to complete the execution
|
|
127
121
|
tx.moveCall({
|
|
128
|
-
target: `${
|
|
122
|
+
target: `${offrampPackageId}::offramp::finish_execute`,
|
|
129
123
|
arguments: [
|
|
130
124
|
tx.object(ccipObjectRef),
|
|
131
125
|
tx.object(offrampStateObject),
|
package/src/sui/objects.ts
CHANGED
|
@@ -135,11 +135,12 @@ export async function getReceiverModule(
|
|
|
135
135
|
ccipObjectRef: string,
|
|
136
136
|
receiverPackageId: string,
|
|
137
137
|
) {
|
|
138
|
+
const ccipBarePackageId = ccipPackageId.split('::')[0]!
|
|
138
139
|
// Call get_receiver_config from receiver_registry contract
|
|
139
140
|
const tx = new Transaction()
|
|
140
141
|
|
|
141
142
|
tx.moveCall({
|
|
142
|
-
target: `${
|
|
143
|
+
target: `${ccipBarePackageId}::receiver_registry::get_receiver_config`,
|
|
143
144
|
arguments: [tx.object(ccipObjectRef), tx.pure.address(receiverPackageId)],
|
|
144
145
|
})
|
|
145
146
|
|
|
@@ -207,12 +208,13 @@ export async function fetchTokenConfigs(
|
|
|
207
208
|
]
|
|
208
209
|
|
|
209
210
|
// Fetch token config for each unique token address
|
|
211
|
+
const ccipBarePackageId = ccipPackageId.split('::')[0]!
|
|
210
212
|
for (const tokenAddress of tokenAddresses) {
|
|
211
213
|
const tx = new Transaction()
|
|
212
214
|
|
|
213
215
|
// Call get_token_config_struct from token_admin_registry
|
|
214
216
|
tx.moveCall({
|
|
215
|
-
target: `${
|
|
217
|
+
target: `${ccipBarePackageId}::token_admin_registry::get_token_config_struct`,
|
|
216
218
|
arguments: [tx.object(ccipObjectRef), tx.pure.address(tokenAddress)],
|
|
217
219
|
})
|
|
218
220
|
|
package/src/sui/types.ts
CHANGED
|
@@ -2,12 +2,21 @@ import { bcs } from '@mysten/sui/bcs'
|
|
|
2
2
|
import { concat } from 'ethers'
|
|
3
3
|
|
|
4
4
|
import { type SuiExtraArgsV1, SuiExtraArgsV1Tag } from '../extra-args.ts'
|
|
5
|
-
import type { CCIPMessage_V1_6 } from '../types.ts'
|
|
5
|
+
import type { CCIPMessage_V1_6, ChainFamily } from '../types.ts'
|
|
6
6
|
import { getAddressBytes, getDataBytes } from '../utils.ts'
|
|
7
7
|
|
|
8
8
|
/** Sui-specific CCIP v1.6 message type with Sui extra args. */
|
|
9
9
|
export type CCIPMessage_V1_6_Sui = CCIPMessage_V1_6 & SuiExtraArgsV1
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Unsigned Sui transaction, serialized via Transaction#serialize().
|
|
13
|
+
* Reconstruct with Transaction.from(transactions[0]).
|
|
14
|
+
*/
|
|
15
|
+
export type UnsignedSuiTx = {
|
|
16
|
+
family: typeof ChainFamily.Sui
|
|
17
|
+
transactions: [string]
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
export const SuiExtraArgsV1Codec = bcs.struct('SuiExtraArgsV1', {
|
|
12
21
|
gasLimit: bcs.u64(),
|
|
13
22
|
allowOutOfOrderExecution: bcs.bool(),
|
package/src/ton/index.ts
CHANGED
|
@@ -3,7 +3,18 @@ import { Buffer } from 'buffer'
|
|
|
3
3
|
import { type Transaction, Address, Cell, beginCell, toNano } from '@ton/core'
|
|
4
4
|
import { TonClient } from '@ton/ton'
|
|
5
5
|
import { type AxiosAdapter, getAdapter } from 'axios'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type BytesLike,
|
|
8
|
+
concat,
|
|
9
|
+
dataLength,
|
|
10
|
+
dataSlice,
|
|
11
|
+
hexlify,
|
|
12
|
+
isBytesLike,
|
|
13
|
+
isHexString,
|
|
14
|
+
toBeArray,
|
|
15
|
+
toBeHex,
|
|
16
|
+
toBigInt,
|
|
17
|
+
} from 'ethers'
|
|
7
18
|
import { type Memoized, memoize } from 'micro-memoize'
|
|
8
19
|
import type { PickDeep } from 'type-fest'
|
|
9
20
|
|
|
@@ -45,6 +56,7 @@ import {
|
|
|
45
56
|
bytesToBuffer,
|
|
46
57
|
createRateLimitedFetch,
|
|
47
58
|
decodeAddress,
|
|
59
|
+
getDataBytes,
|
|
48
60
|
networkInfo,
|
|
49
61
|
parseTypeAndVersion,
|
|
50
62
|
sleep,
|
|
@@ -64,6 +76,16 @@ function isTvmError(error: unknown): error is Error & { exitCode: number } {
|
|
|
64
76
|
return error instanceof Error && 'exitCode' in error && typeof error.exitCode === 'number'
|
|
65
77
|
}
|
|
66
78
|
|
|
79
|
+
function bitsToBytes(bits: string): Uint8Array {
|
|
80
|
+
return Uint8Array.from(bits.match(/.{1,8}/g)!.map((byte) => parseInt(byte.padEnd(8, '0'), 2)))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function bytesToBits(bytes: Uint8Array): string {
|
|
84
|
+
return Array.from(bytes)
|
|
85
|
+
.map((B) => B.toString(2).padStart(8, '0'))
|
|
86
|
+
.join('')
|
|
87
|
+
}
|
|
88
|
+
|
|
67
89
|
/**
|
|
68
90
|
* TON chain implementation supporting TON networks.
|
|
69
91
|
*
|
|
@@ -702,14 +724,14 @@ export class TONChain extends Chain<typeof ChainFamily.TON> {
|
|
|
702
724
|
*/
|
|
703
725
|
static encodeExtraArgs(args: ExtraArgs): string {
|
|
704
726
|
if ('gasLimit' in args && 'allowOutOfOrderExecution' in args) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
727
|
+
return concat([
|
|
728
|
+
EVMExtraArgsV2Tag,
|
|
729
|
+
bitsToBytes(
|
|
730
|
+
'1' +
|
|
731
|
+
bytesToBits(toBeArray(args.gasLimit, 32)) +
|
|
732
|
+
(args.allowOutOfOrderExecution ? '1' : '0'),
|
|
733
|
+
),
|
|
734
|
+
])
|
|
713
735
|
}
|
|
714
736
|
return '0x'
|
|
715
737
|
}
|
|
@@ -729,25 +751,24 @@ export class TONChain extends Chain<typeof ChainFamily.TON> {
|
|
|
729
751
|
static decodeExtraArgs(
|
|
730
752
|
extraArgs: BytesLike,
|
|
731
753
|
): (EVMExtraArgsV2 & { _tag: 'EVMExtraArgsV2' }) | undefined {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
754
|
+
if (dataSlice(extraArgs, 0, 4) !== EVMExtraArgsV2Tag || dataLength(extraArgs) < 5) return
|
|
755
|
+
const data = getDataBytes(extraArgs).subarray(4)
|
|
756
|
+
let bits = bytesToBits(data)
|
|
757
|
+
let gasLimit = 0n
|
|
758
|
+
if (bits[0] === '1') {
|
|
759
|
+
if (bits.length < 1 + 32 * 8) return
|
|
760
|
+
gasLimit = toBigInt(bitsToBytes(bits.substring(1, 1 + 32 * 8)))
|
|
761
|
+
bits = bits.substring(1 + 32 * 8)
|
|
762
|
+
} else {
|
|
763
|
+
bits = bits.substring(1)
|
|
764
|
+
}
|
|
738
765
|
|
|
739
|
-
|
|
740
|
-
const magicTag = slice.loadUint(32)
|
|
741
|
-
if (magicTag !== Number(EVMExtraArgsV2Tag)) return undefined
|
|
766
|
+
const allowOutOfOrderExecution = bits[0] === '1'
|
|
742
767
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
748
|
-
} catch {
|
|
749
|
-
// Return undefined for any parsing errors (invalid BOC, malformed data, etc.)
|
|
750
|
-
return undefined
|
|
768
|
+
return {
|
|
769
|
+
_tag: 'EVMExtraArgsV2',
|
|
770
|
+
gasLimit,
|
|
771
|
+
allowOutOfOrderExecution,
|
|
751
772
|
}
|
|
752
773
|
}
|
|
753
774
|
|
package/src/utils.ts
CHANGED
|
@@ -190,10 +190,16 @@ export const networkInfo = memoize(function networkInfo_(
|
|
|
190
190
|
|
|
191
191
|
const BLOCK_RANGE = 10_000
|
|
192
192
|
/**
|
|
193
|
-
* Generates
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
|
|
193
|
+
* Generates block ranges for paginated log queries.
|
|
194
|
+
*
|
|
195
|
+
* @param params - Range parameters:
|
|
196
|
+
* - `singleBlock` - yields a single `{ fromBlock, toBlock }` for that block.
|
|
197
|
+
* - `endBlock` + optional `startBlock` - if `startBlock` is given, moves forward
|
|
198
|
+
* from there up to `endBlock`; otherwise moves backward from `endBlock` to genesis.
|
|
199
|
+
* - `page` - step size per range (default 10 000).
|
|
200
|
+
* @returns Generator of `{ fromBlock, toBlock }` pairs, optionally with a `progress` percentage
|
|
201
|
+
* string when iterating forward.
|
|
202
|
+
*/
|
|
197
203
|
export function* blockRangeGenerator(
|
|
198
204
|
params: { page?: number } & ({ endBlock: number; startBlock?: number } | { singleBlock: number }),
|
|
199
205
|
) {
|