@chainlink/ccip-sdk 0.96.0 → 1.0.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/README.md +12 -9
- package/dist/api/index.d.ts +21 -8
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +42 -13
- package/dist/api/index.js.map +1 -1
- package/dist/api/types.d.ts +0 -2
- package/dist/api/types.d.ts.map +1 -1
- package/dist/aptos/exec.d.ts +2 -2
- package/dist/aptos/exec.d.ts.map +1 -1
- package/dist/aptos/exec.js.map +1 -1
- package/dist/aptos/hasher.d.ts.map +1 -1
- package/dist/aptos/hasher.js +1 -1
- package/dist/aptos/hasher.js.map +1 -1
- package/dist/aptos/index.d.ts +17 -16
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +42 -73
- package/dist/aptos/index.js.map +1 -1
- package/dist/aptos/logs.d.ts +2 -2
- package/dist/aptos/logs.d.ts.map +1 -1
- package/dist/aptos/types.d.ts +2 -19
- package/dist/aptos/types.d.ts.map +1 -1
- package/dist/aptos/types.js +0 -11
- package/dist/aptos/types.js.map +1 -1
- package/dist/chain.d.ts +538 -158
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +132 -19
- package/dist/chain.js.map +1 -1
- package/dist/commits.d.ts +4 -6
- package/dist/commits.d.ts.map +1 -1
- package/dist/commits.js +4 -4
- package/dist/commits.js.map +1 -1
- package/dist/errors/CCIPError.d.ts +33 -4
- package/dist/errors/CCIPError.d.ts.map +1 -1
- package/dist/errors/CCIPError.js +33 -4
- package/dist/errors/CCIPError.js.map +1 -1
- package/dist/errors/codes.d.ts +3 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +3 -1
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/index.d.ts +4 -4
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +4 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/recovery.d.ts.map +1 -1
- package/dist/errors/recovery.js +4 -1
- package/dist/errors/recovery.js.map +1 -1
- package/dist/errors/specialized.d.ts +1695 -120
- package/dist/errors/specialized.d.ts.map +1 -1
- package/dist/errors/specialized.js +1715 -123
- package/dist/errors/specialized.js.map +1 -1
- package/dist/errors/utils.d.ts.map +1 -1
- package/dist/errors/utils.js +0 -1
- package/dist/errors/utils.js.map +1 -1
- package/dist/evm/abi/OffRamp_2_0.d.ts +764 -0
- package/dist/evm/abi/OffRamp_2_0.d.ts.map +1 -0
- package/dist/evm/abi/OffRamp_2_0.js +744 -0
- package/dist/evm/abi/OffRamp_2_0.js.map +1 -0
- package/dist/evm/abi/OnRamp_2_0.d.ts +925 -0
- package/dist/evm/abi/OnRamp_2_0.d.ts.map +1 -0
- package/dist/evm/abi/OnRamp_2_0.js +992 -0
- package/dist/evm/abi/OnRamp_2_0.js.map +1 -0
- package/dist/evm/const.d.ts +12 -2
- package/dist/evm/const.d.ts.map +1 -1
- package/dist/evm/const.js +8 -2
- package/dist/evm/const.js.map +1 -1
- package/dist/evm/errors.d.ts.map +1 -1
- package/dist/evm/errors.js +7 -2
- package/dist/evm/errors.js.map +1 -1
- package/dist/evm/extra-args.d.ts.map +1 -1
- package/dist/evm/extra-args.js +5 -24
- package/dist/evm/extra-args.js.map +1 -1
- package/dist/evm/hasher.d.ts.map +1 -1
- package/dist/evm/hasher.js +23 -13
- package/dist/evm/hasher.js.map +1 -1
- package/dist/evm/index.d.ts +73 -16
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +241 -146
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/logs.d.ts +1 -1
- package/dist/evm/logs.js +1 -1
- package/dist/evm/messages.d.ts +59 -5
- package/dist/evm/messages.d.ts.map +1 -1
- package/dist/evm/messages.js +210 -0
- package/dist/evm/messages.js.map +1 -1
- package/dist/evm/offchain.d.ts +1 -14
- package/dist/evm/offchain.d.ts.map +1 -1
- package/dist/evm/offchain.js +1 -133
- package/dist/evm/offchain.js.map +1 -1
- package/dist/evm/types.d.ts +7 -2
- package/dist/evm/types.d.ts.map +1 -1
- package/dist/evm/types.js +22 -1
- package/dist/evm/types.js.map +1 -1
- package/dist/execution.d.ts +62 -22
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +98 -61
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +13 -3
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +13 -3
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +25 -2
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +30 -4
- 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 +2 -1
- package/dist/index.js.map +1 -1
- package/dist/offchain.d.ts +23 -6
- package/dist/offchain.d.ts.map +1 -1
- package/dist/offchain.js +92 -17
- package/dist/offchain.js.map +1 -1
- package/dist/requests.d.ts +85 -14
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +99 -17
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts.map +1 -1
- package/dist/selectors.js +12 -0
- package/dist/selectors.js.map +1 -1
- package/dist/shared/bcs-codecs.d.ts +61 -0
- package/dist/shared/bcs-codecs.d.ts.map +1 -0
- package/dist/shared/bcs-codecs.js +102 -0
- package/dist/shared/bcs-codecs.js.map +1 -0
- package/dist/shared/constants.d.ts +3 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +3 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/solana/exec.d.ts +2 -2
- package/dist/solana/exec.d.ts.map +1 -1
- package/dist/solana/exec.js.map +1 -1
- package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts +16 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts.map +1 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.js +16 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.js.map +1 -1
- package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_ROUTER.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_ROUTER.js +1 -1
- package/dist/solana/index.d.ts +85 -24
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +69 -37
- package/dist/solana/index.js.map +1 -1
- package/dist/solana/offchain.d.ts +1 -13
- package/dist/solana/offchain.d.ts.map +1 -1
- package/dist/solana/offchain.js +1 -66
- package/dist/solana/offchain.js.map +1 -1
- package/dist/solana/utils.d.ts +4 -4
- package/dist/solana/utils.d.ts.map +1 -1
- package/dist/solana/utils.js +1 -1
- package/dist/solana/utils.js.map +1 -1
- package/dist/sui/hasher.d.ts.map +1 -1
- package/dist/sui/hasher.js +1 -1
- package/dist/sui/hasher.js.map +1 -1
- package/dist/sui/index.d.ts +18 -18
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +38 -39
- package/dist/sui/index.js.map +1 -1
- package/dist/sui/manuallyExec/encoder.d.ts +2 -2
- package/dist/sui/manuallyExec/encoder.d.ts.map +1 -1
- package/dist/sui/manuallyExec/encoder.js.map +1 -1
- package/dist/sui/manuallyExec/index.d.ts +2 -2
- package/dist/sui/manuallyExec/index.d.ts.map +1 -1
- package/dist/ton/exec.d.ts +3 -3
- package/dist/ton/exec.d.ts.map +1 -1
- package/dist/ton/exec.js +1 -1
- package/dist/ton/exec.js.map +1 -1
- package/dist/ton/index.d.ts +14 -22
- package/dist/ton/index.d.ts.map +1 -1
- package/dist/ton/index.js +26 -35
- package/dist/ton/index.js.map +1 -1
- package/dist/ton/types.d.ts +3 -5
- package/dist/ton/types.d.ts.map +1 -1
- package/dist/ton/types.js.map +1 -1
- package/dist/types.d.ts +55 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +65 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +74 -2
- package/dist/utils.js.map +1 -1
- package/package.json +14 -10
- package/src/api/index.ts +53 -17
- package/src/api/types.ts +0 -2
- package/src/aptos/exec.ts +2 -2
- package/src/aptos/hasher.ts +1 -1
- package/src/aptos/index.ts +55 -100
- package/src/aptos/logs.ts +2 -2
- package/src/aptos/types.ts +2 -15
- package/src/chain.ts +594 -171
- package/src/commits.ts +9 -9
- package/src/errors/CCIPError.ts +33 -4
- package/src/errors/codes.ts +3 -1
- package/src/errors/index.ts +4 -0
- package/src/errors/recovery.ts +7 -1
- package/src/errors/specialized.ts +1726 -130
- package/src/errors/utils.ts +0 -1
- package/src/evm/abi/OffRamp_2_0.ts +743 -0
- package/src/evm/abi/OnRamp_2_0.ts +991 -0
- package/src/evm/const.ts +10 -3
- package/src/evm/errors.ts +6 -2
- package/src/evm/extra-args.ts +4 -21
- package/src/evm/hasher.ts +30 -18
- package/src/evm/index.ts +314 -176
- package/src/evm/logs.ts +1 -1
- package/src/evm/messages.ts +323 -11
- package/src/evm/offchain.ts +2 -191
- package/src/evm/types.ts +20 -2
- package/src/execution.ts +125 -86
- package/src/extra-args.ts +13 -3
- package/src/gas.ts +29 -3
- package/src/index.ts +10 -3
- package/src/offchain.ts +125 -28
- package/src/requests.ts +114 -19
- package/src/selectors.ts +12 -0
- package/src/shared/bcs-codecs.ts +132 -0
- package/src/shared/constants.ts +2 -0
- package/src/solana/exec.ts +4 -4
- package/src/solana/idl/1.6.0/BASE_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_COMMON.ts +32 -2
- package/src/solana/idl/1.6.0/CCIP_OFFRAMP.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_ROUTER.ts +2 -2
- package/src/solana/index.ts +110 -85
- package/src/solana/offchain.ts +3 -100
- package/src/solana/utils.ts +8 -5
- package/src/sui/hasher.ts +1 -1
- package/src/sui/index.ts +55 -59
- package/src/sui/manuallyExec/encoder.ts +2 -2
- package/src/sui/manuallyExec/index.ts +2 -2
- package/src/ton/exec.ts +4 -7
- package/src/ton/index.ts +45 -53
- package/src/ton/types.ts +4 -7
- package/src/types.ts +81 -37
- package/src/utils.ts +73 -2
- package/dist/aptos/utils.d.ts +0 -12
- package/dist/aptos/utils.d.ts.map +0 -1
- package/dist/aptos/utils.js +0 -15
- package/dist/aptos/utils.js.map +0 -1
- package/src/aptos/utils.ts +0 -24
package/src/evm/logs.ts
CHANGED
|
@@ -183,7 +183,7 @@ async function getFallbackArchiveLogs(
|
|
|
183
183
|
* - If undefined (default): paginate main provider only by filter.page
|
|
184
184
|
* - If false: first try whole range with main provider, then fallback to archive provider
|
|
185
185
|
* - If true: don't paginate (throw if can't fetch wide range from either provider)
|
|
186
|
-
* @param ctx - Context object containing provider, logger and
|
|
186
|
+
* @param ctx - Context object containing provider, logger and destroy$ notify promise
|
|
187
187
|
* @returns Async iterator of logs.
|
|
188
188
|
*/
|
|
189
189
|
export async function* getEvmLogs(
|
package/src/evm/messages.ts
CHANGED
|
@@ -1,21 +1,310 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
AbiParameterToPrimitiveType,
|
|
3
|
+
AbiParametersToPrimitiveTypes,
|
|
4
|
+
ExtractAbiEvent,
|
|
5
|
+
} from 'abitype'
|
|
6
|
+
import {
|
|
7
|
+
type Addressable,
|
|
8
|
+
type BytesLike,
|
|
9
|
+
type Result,
|
|
10
|
+
dataSlice,
|
|
11
|
+
hexlify,
|
|
12
|
+
toBigInt,
|
|
13
|
+
toNumber,
|
|
14
|
+
} from 'ethers'
|
|
15
|
+
import type { Simplify } from 'type-fest'
|
|
3
16
|
|
|
17
|
+
import { CCIPMessageDecodeError } from '../errors/index.ts'
|
|
4
18
|
import type { EVMExtraArgsV2 } from '../extra-args.ts'
|
|
5
|
-
import type { CCIPVersion, MergeArrayElements } from '../types.ts'
|
|
19
|
+
import type { CCIPVersion, ChainFamily, MergeArrayElements } from '../types.ts'
|
|
20
|
+
import { decodeAddress, getDataBytes, networkInfo } from '../utils.ts'
|
|
6
21
|
import type EVM2EVMOnRamp_1_5_ABI from './abi/OnRamp_1_5.ts'
|
|
7
22
|
import type OnRamp_1_6_ABI from './abi/OnRamp_1_6.ts'
|
|
23
|
+
import type OnRamp_2_0_ABI from './abi/OnRamp_2_0.ts'
|
|
8
24
|
import { defaultAbiCoder } from './const.ts'
|
|
9
25
|
|
|
10
26
|
/** Utility type that cleans up address types to just `string`. */
|
|
11
27
|
export type CleanAddressable<T> = T extends string | Addressable
|
|
12
28
|
? string
|
|
13
|
-
: T extends
|
|
29
|
+
: T extends { [K: string]: unknown } | [...unknown[]]
|
|
14
30
|
? { [K in keyof T]: CleanAddressable<T[K]> }
|
|
15
|
-
: T extends readonly unknown[]
|
|
16
|
-
? readonly CleanAddressable<T[
|
|
31
|
+
: T extends { readonly [K: string]: unknown } | readonly [...unknown[]]
|
|
32
|
+
? { readonly [K in keyof T]: CleanAddressable<T[K]> }
|
|
17
33
|
: T
|
|
18
34
|
|
|
35
|
+
/** Token transfer in MessageV1 format. */
|
|
36
|
+
export type TokenTransferV1 = {
|
|
37
|
+
amount: bigint
|
|
38
|
+
sourcePoolAddress: string
|
|
39
|
+
sourceTokenAddress: string
|
|
40
|
+
destTokenAddress: string
|
|
41
|
+
tokenReceiver: string
|
|
42
|
+
extraData: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** MessageV1 struct matching the Solidity MessageV1Codec format. */
|
|
46
|
+
export type MessageV1 = {
|
|
47
|
+
sourceChainSelector: bigint
|
|
48
|
+
destChainSelector: bigint
|
|
49
|
+
messageNumber: bigint
|
|
50
|
+
executionGasLimit: number
|
|
51
|
+
ccipReceiveGasLimit: number
|
|
52
|
+
finality: number
|
|
53
|
+
ccvAndExecutorHash: string
|
|
54
|
+
onRampAddress: string
|
|
55
|
+
offRampAddress: string
|
|
56
|
+
sender: string
|
|
57
|
+
receiver: string
|
|
58
|
+
destBlob: string
|
|
59
|
+
tokenTransfer: readonly TokenTransferV1[]
|
|
60
|
+
data: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Decodes a TokenTransferV1 from bytes.
|
|
65
|
+
* @param encoded - The encoded bytes.
|
|
66
|
+
* @param offset - The starting offset.
|
|
67
|
+
* @param sourceFamily - The source chain family for source addresses.
|
|
68
|
+
* @param destFamily - The destination chain family for dest addresses.
|
|
69
|
+
* @returns The decoded token transfer and the new offset.
|
|
70
|
+
*/
|
|
71
|
+
function decodeTokenTransferV1(
|
|
72
|
+
encoded: Uint8Array,
|
|
73
|
+
offset: number,
|
|
74
|
+
sourceFamily: ChainFamily,
|
|
75
|
+
destFamily: ChainFamily,
|
|
76
|
+
): { tokenTransfer: TokenTransferV1; newOffset: number } {
|
|
77
|
+
// version (1 byte)
|
|
78
|
+
if (offset >= encoded.length) throw new CCIPMessageDecodeError('TOKEN_TRANSFER_VERSION')
|
|
79
|
+
const version = encoded[offset++]!
|
|
80
|
+
if (version !== 1) throw new CCIPMessageDecodeError(`Invalid encoding version: ${version}`)
|
|
81
|
+
|
|
82
|
+
// amount (32 bytes)
|
|
83
|
+
if (offset + 32 > encoded.length) throw new CCIPMessageDecodeError('TOKEN_TRANSFER_AMOUNT')
|
|
84
|
+
const amount = toBigInt(dataSlice(encoded, offset, offset + 32))
|
|
85
|
+
offset += 32
|
|
86
|
+
|
|
87
|
+
// sourcePoolAddressLength and sourcePoolAddress
|
|
88
|
+
if (offset >= encoded.length) {
|
|
89
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_SOURCE_POOL_LENGTH')
|
|
90
|
+
}
|
|
91
|
+
const sourcePoolAddressLength = encoded[offset++]!
|
|
92
|
+
if (offset + sourcePoolAddressLength > encoded.length) {
|
|
93
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_SOURCE_POOL_CONTENT')
|
|
94
|
+
}
|
|
95
|
+
const sourcePoolAddress = decodeAddress(
|
|
96
|
+
dataSlice(encoded, offset, offset + sourcePoolAddressLength),
|
|
97
|
+
sourceFamily,
|
|
98
|
+
)
|
|
99
|
+
offset += sourcePoolAddressLength
|
|
100
|
+
|
|
101
|
+
// sourceTokenAddressLength and sourceTokenAddress
|
|
102
|
+
if (offset >= encoded.length) {
|
|
103
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_SOURCE_TOKEN_LENGTH')
|
|
104
|
+
}
|
|
105
|
+
const sourceTokenAddressLength = encoded[offset++]!
|
|
106
|
+
if (offset + sourceTokenAddressLength > encoded.length) {
|
|
107
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_SOURCE_TOKEN_CONTENT')
|
|
108
|
+
}
|
|
109
|
+
const sourceTokenAddress = decodeAddress(
|
|
110
|
+
dataSlice(encoded, offset, offset + sourceTokenAddressLength),
|
|
111
|
+
sourceFamily,
|
|
112
|
+
)
|
|
113
|
+
offset += sourceTokenAddressLength
|
|
114
|
+
|
|
115
|
+
// destTokenAddressLength and destTokenAddress
|
|
116
|
+
if (offset >= encoded.length) {
|
|
117
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_DEST_TOKEN_LENGTH')
|
|
118
|
+
}
|
|
119
|
+
const destTokenAddressLength = encoded[offset++]!
|
|
120
|
+
if (offset + destTokenAddressLength > encoded.length) {
|
|
121
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_DEST_TOKEN_CONTENT')
|
|
122
|
+
}
|
|
123
|
+
const destTokenAddress = decodeAddress(
|
|
124
|
+
dataSlice(encoded, offset, offset + destTokenAddressLength),
|
|
125
|
+
destFamily,
|
|
126
|
+
)
|
|
127
|
+
offset += destTokenAddressLength
|
|
128
|
+
|
|
129
|
+
// tokenReceiverLength and tokenReceiver
|
|
130
|
+
if (offset >= encoded.length) {
|
|
131
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_TOKEN_RECEIVER_LENGTH')
|
|
132
|
+
}
|
|
133
|
+
const tokenReceiverLength = encoded[offset++]!
|
|
134
|
+
if (offset + tokenReceiverLength > encoded.length) {
|
|
135
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_TOKEN_RECEIVER_CONTENT')
|
|
136
|
+
}
|
|
137
|
+
const tokenReceiver = decodeAddress(
|
|
138
|
+
dataSlice(encoded, offset, offset + tokenReceiverLength),
|
|
139
|
+
destFamily,
|
|
140
|
+
)
|
|
141
|
+
offset += tokenReceiverLength
|
|
142
|
+
|
|
143
|
+
// extraDataLength and extraData
|
|
144
|
+
if (offset + 2 > encoded.length) {
|
|
145
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_EXTRA_DATA_LENGTH')
|
|
146
|
+
}
|
|
147
|
+
const extraDataLength = toNumber(dataSlice(encoded, offset, offset + 2))
|
|
148
|
+
offset += 2
|
|
149
|
+
if (offset + extraDataLength > encoded.length) {
|
|
150
|
+
throw new CCIPMessageDecodeError('TOKEN_TRANSFER_EXTRA_DATA_CONTENT')
|
|
151
|
+
}
|
|
152
|
+
const extraData = hexlify(dataSlice(encoded, offset, offset + extraDataLength))
|
|
153
|
+
offset += extraDataLength
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
tokenTransfer: {
|
|
157
|
+
amount,
|
|
158
|
+
sourcePoolAddress,
|
|
159
|
+
sourceTokenAddress,
|
|
160
|
+
destTokenAddress,
|
|
161
|
+
tokenReceiver,
|
|
162
|
+
extraData,
|
|
163
|
+
},
|
|
164
|
+
newOffset: offset,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Decodes a MessageV1 from bytes following the v1 protocol format.
|
|
170
|
+
* @param encodedMessage - The encoded message bytes to decode.
|
|
171
|
+
* @returns The decoded MessageV1 struct.
|
|
172
|
+
*/
|
|
173
|
+
export function decodeMessageV1(encodedMessage: BytesLike): MessageV1 {
|
|
174
|
+
const MESSAGE_V1_BASE_SIZE = 77
|
|
175
|
+
const encoded = getDataBytes(encodedMessage)
|
|
176
|
+
|
|
177
|
+
if (encoded.length < MESSAGE_V1_BASE_SIZE) throw new CCIPMessageDecodeError('MESSAGE_MIN_SIZE')
|
|
178
|
+
|
|
179
|
+
const version = encoded[0]!
|
|
180
|
+
if (version !== 1) throw new CCIPMessageDecodeError(`Invalid encoding version: ${version}`)
|
|
181
|
+
|
|
182
|
+
// sourceChainSelector (8 bytes, big endian)
|
|
183
|
+
const sourceChainSelector = toBigInt(dataSlice(encoded, 1, 9))
|
|
184
|
+
|
|
185
|
+
// destChainSelector (8 bytes, big endian)
|
|
186
|
+
const destChainSelector = toBigInt(dataSlice(encoded, 9, 17))
|
|
187
|
+
|
|
188
|
+
// Get chain families for address decoding
|
|
189
|
+
const sourceNetworkInfo = networkInfo(sourceChainSelector)
|
|
190
|
+
const destNetworkInfo = networkInfo(destChainSelector)
|
|
191
|
+
const sourceFamily = sourceNetworkInfo.family
|
|
192
|
+
const destFamily = destNetworkInfo.family
|
|
193
|
+
|
|
194
|
+
// messageNumber (8 bytes, big endian)
|
|
195
|
+
const messageNumber = toBigInt(dataSlice(encoded, 17, 25))
|
|
196
|
+
|
|
197
|
+
// executionGasLimit (4 bytes, big endian)
|
|
198
|
+
const executionGasLimit = toNumber(dataSlice(encoded, 25, 29))
|
|
199
|
+
|
|
200
|
+
// ccipReceiveGasLimit (4 bytes, big endian)
|
|
201
|
+
const ccipReceiveGasLimit = toNumber(dataSlice(encoded, 29, 33))
|
|
202
|
+
|
|
203
|
+
// finality (2 bytes, big endian)
|
|
204
|
+
const finality = toNumber(dataSlice(encoded, 33, 35))
|
|
205
|
+
|
|
206
|
+
// ccvAndExecutorHash (32 bytes)
|
|
207
|
+
const ccvAndExecutorHash = hexlify(dataSlice(encoded, 35, 67))
|
|
208
|
+
|
|
209
|
+
// onRampAddressLength and onRampAddress
|
|
210
|
+
let offset = 67
|
|
211
|
+
if (offset >= encoded.length) throw new CCIPMessageDecodeError('MESSAGE_ONRAMP_ADDRESS_LENGTH')
|
|
212
|
+
const onRampAddressLength = encoded[offset++]!
|
|
213
|
+
if (offset + onRampAddressLength > encoded.length) {
|
|
214
|
+
throw new CCIPMessageDecodeError('MESSAGE_ONRAMP_ADDRESS_CONTENT')
|
|
215
|
+
}
|
|
216
|
+
const onRampAddress = decodeAddress(
|
|
217
|
+
dataSlice(encoded, offset, offset + onRampAddressLength),
|
|
218
|
+
sourceFamily,
|
|
219
|
+
)
|
|
220
|
+
offset += onRampAddressLength
|
|
221
|
+
|
|
222
|
+
// offRampAddressLength and offRampAddress
|
|
223
|
+
if (offset >= encoded.length) throw new CCIPMessageDecodeError('MESSAGE_OFFRAMP_ADDRESS_LENGTH')
|
|
224
|
+
const offRampAddressLength = encoded[offset++]!
|
|
225
|
+
if (offset + offRampAddressLength > encoded.length) {
|
|
226
|
+
throw new CCIPMessageDecodeError('MESSAGE_OFFRAMP_ADDRESS_CONTENT')
|
|
227
|
+
}
|
|
228
|
+
const offRampAddress = decodeAddress(
|
|
229
|
+
dataSlice(encoded, offset, offset + offRampAddressLength),
|
|
230
|
+
destFamily,
|
|
231
|
+
)
|
|
232
|
+
offset += offRampAddressLength
|
|
233
|
+
|
|
234
|
+
// senderLength and sender
|
|
235
|
+
if (offset >= encoded.length) throw new CCIPMessageDecodeError('MESSAGE_SENDER_LENGTH')
|
|
236
|
+
const senderLength = encoded[offset++]!
|
|
237
|
+
if (offset + senderLength > encoded.length) {
|
|
238
|
+
throw new CCIPMessageDecodeError('MESSAGE_SENDER_CONTENT')
|
|
239
|
+
}
|
|
240
|
+
const sender = decodeAddress(dataSlice(encoded, offset, offset + senderLength), sourceFamily)
|
|
241
|
+
offset += senderLength
|
|
242
|
+
|
|
243
|
+
// receiverLength and receiver
|
|
244
|
+
if (offset >= encoded.length) throw new CCIPMessageDecodeError('MESSAGE_RECEIVER_LENGTH')
|
|
245
|
+
const receiverLength = encoded[offset++]!
|
|
246
|
+
if (offset + receiverLength > encoded.length) {
|
|
247
|
+
throw new CCIPMessageDecodeError('MESSAGE_RECEIVER_CONTENT')
|
|
248
|
+
}
|
|
249
|
+
const receiver = decodeAddress(dataSlice(encoded, offset, offset + receiverLength), destFamily)
|
|
250
|
+
offset += receiverLength
|
|
251
|
+
|
|
252
|
+
// destBlobLength and destBlob
|
|
253
|
+
if (offset + 2 > encoded.length) throw new CCIPMessageDecodeError('MESSAGE_DEST_BLOB_LENGTH')
|
|
254
|
+
const destBlobLength = toNumber(dataSlice(encoded, offset, offset + 2))
|
|
255
|
+
offset += 2
|
|
256
|
+
if (offset + destBlobLength > encoded.length) {
|
|
257
|
+
throw new CCIPMessageDecodeError('MESSAGE_DEST_BLOB_CONTENT')
|
|
258
|
+
}
|
|
259
|
+
const destBlob = hexlify(dataSlice(encoded, offset, offset + destBlobLength))
|
|
260
|
+
offset += destBlobLength
|
|
261
|
+
|
|
262
|
+
// tokenTransferLength and tokenTransfer
|
|
263
|
+
if (offset + 2 > encoded.length) throw new CCIPMessageDecodeError('MESSAGE_TOKEN_TRANSFER_LENGTH')
|
|
264
|
+
const tokenTransferLength = toNumber(dataSlice(encoded, offset, offset + 2))
|
|
265
|
+
offset += 2
|
|
266
|
+
|
|
267
|
+
// Decode token transfer, which is either 0 or 1
|
|
268
|
+
const tokenTransfer: TokenTransferV1[] = []
|
|
269
|
+
if (tokenTransferLength > 0) {
|
|
270
|
+
const expectedEnd = offset + tokenTransferLength
|
|
271
|
+
const result = decodeTokenTransferV1(encoded, offset, sourceFamily, destFamily)
|
|
272
|
+
tokenTransfer.push(result.tokenTransfer)
|
|
273
|
+
offset = result.newOffset
|
|
274
|
+
if (offset !== expectedEnd) throw new CCIPMessageDecodeError('MESSAGE_TOKEN_TRANSFER_CONTENT')
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// dataLength and data
|
|
278
|
+
if (offset + 2 > encoded.length) throw new CCIPMessageDecodeError('MESSAGE_DATA_LENGTH')
|
|
279
|
+
const dataLength = toNumber(dataSlice(encoded, offset, offset + 2))
|
|
280
|
+
offset += 2
|
|
281
|
+
if (offset + dataLength > encoded.length) {
|
|
282
|
+
throw new CCIPMessageDecodeError('MESSAGE_DATA_CONTENT')
|
|
283
|
+
}
|
|
284
|
+
const data = hexlify(dataSlice(encoded, offset, offset + dataLength))
|
|
285
|
+
offset += dataLength
|
|
286
|
+
|
|
287
|
+
// Ensure we've consumed all bytes
|
|
288
|
+
if (offset !== encoded.length) throw new CCIPMessageDecodeError('MESSAGE_FINAL_OFFSET')
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
sourceChainSelector,
|
|
292
|
+
destChainSelector,
|
|
293
|
+
messageNumber,
|
|
294
|
+
executionGasLimit,
|
|
295
|
+
ccipReceiveGasLimit,
|
|
296
|
+
finality,
|
|
297
|
+
ccvAndExecutorHash,
|
|
298
|
+
onRampAddress,
|
|
299
|
+
offRampAddress,
|
|
300
|
+
sender,
|
|
301
|
+
receiver,
|
|
302
|
+
destBlob,
|
|
303
|
+
tokenTransfer,
|
|
304
|
+
data,
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
19
308
|
// v1.2-v1.5 Message ()
|
|
20
309
|
type EVM2AnyMessageRequested = CleanAddressable<
|
|
21
310
|
AbiParametersToPrimitiveTypes<
|
|
@@ -50,12 +339,35 @@ export type CCIPMessage_V1_2_EVM = EVM2AnyMessageRequested
|
|
|
50
339
|
/** v1.6 EVM specialization with EVMExtraArgsV2 and tokenAmounts.*.destGasAmount. */
|
|
51
340
|
export type CCIPMessage_V1_6_EVM = CCIPMessage_V1_6 & EVMExtraArgsV2
|
|
52
341
|
|
|
342
|
+
type MessageSentV2EventParams = ExtractAbiEvent<typeof OnRamp_2_0_ABI, 'CCIPMessageSent'>['inputs']
|
|
343
|
+
type CCIPMessageSentV2 = {
|
|
344
|
+
[N in MessageSentV2EventParams[number]['name']]: CleanAddressable<
|
|
345
|
+
AbiParameterToPrimitiveType<MessageSentV2EventParams[number] & { readonly name: N }>
|
|
346
|
+
>
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* CCIP v2.0 (fka v1.7) Message
|
|
351
|
+
*/
|
|
352
|
+
export type CCIPMessage_V2_0 = Simplify<
|
|
353
|
+
CCIPMessageSentV2 &
|
|
354
|
+
Omit<MessageV1, 'tokenTransfer'> & {
|
|
355
|
+
tokenAmounts: MessageV1['tokenTransfer']
|
|
356
|
+
sequenceNumber: MessageV1['messageNumber']
|
|
357
|
+
feeTokenAmount: bigint
|
|
358
|
+
}
|
|
359
|
+
>
|
|
360
|
+
|
|
53
361
|
/** Union type for CCIP EVM messages across versions. */
|
|
54
|
-
export type CCIPMessage_EVM<V extends CCIPVersion = CCIPVersion> = V extends typeof CCIPVersion.
|
|
55
|
-
?
|
|
56
|
-
: V extends typeof CCIPVersion.
|
|
57
|
-
?
|
|
58
|
-
:
|
|
362
|
+
export type CCIPMessage_EVM<V extends CCIPVersion = CCIPVersion> = V extends typeof CCIPVersion.V2_0
|
|
363
|
+
? CCIPMessage_V2_0
|
|
364
|
+
: V extends typeof CCIPVersion.V1_6
|
|
365
|
+
? CCIPMessage_V1_6_EVM
|
|
366
|
+
: V extends typeof CCIPVersion.V1_5
|
|
367
|
+
? CCIPMessage_V1_5_EVM
|
|
368
|
+
: V extends typeof CCIPVersion.V1_2
|
|
369
|
+
? CCIPMessage_V1_2_EVM
|
|
370
|
+
: never
|
|
59
371
|
|
|
60
372
|
const SourceTokenData =
|
|
61
373
|
'tuple(bytes sourcePoolAddress, bytes destTokenAddress, bytes extraData, uint64 destGasAmount)'
|
package/src/evm/offchain.ts
CHANGED
|
@@ -1,90 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { getLbtcAttestation, getUsdcAttestation } from '../offchain.ts'
|
|
4
|
-
import type {
|
|
5
|
-
CCIPMessage,
|
|
6
|
-
CCIPRequest,
|
|
7
|
-
NetworkType,
|
|
8
|
-
OffchainTokenData,
|
|
9
|
-
WithLogger,
|
|
10
|
-
} from '../types.ts'
|
|
11
|
-
import { networkInfo } from '../utils.ts'
|
|
12
|
-
import { defaultAbiCoder, interfaces, requestsFragments } from './const.ts'
|
|
13
|
-
import { type SourceTokenData, parseSourceTokenData } from './messages.ts'
|
|
14
|
-
|
|
15
|
-
const BURNED_EVENT_1_5 = interfaces.TokenPool_v1_5.getEvent('Burned')!
|
|
16
|
-
const BURNED_EVENT_1_6 = interfaces.TokenPool_v1_6.getEvent('LockedOrBurned')!
|
|
17
|
-
const BURNED_EVENT_TOPIC_HASHES = new Set([BURNED_EVENT_1_5.topicHash, BURNED_EVENT_1_6.topicHash])
|
|
18
|
-
|
|
19
|
-
const USDC_EVENT = EventFragment.from('MessageSent(bytes message)')
|
|
20
|
-
const TRANSFER_EVENT = EventFragment.from('Transfer(address from, address to, uint256 value)')
|
|
21
|
-
|
|
22
|
-
export const LBTC_EVENT = EventFragment.from(
|
|
23
|
-
'DepositToBridge(address fromAddress, bytes32 toAddress, bytes32 payloadHash, bytes payload)',
|
|
24
|
-
)
|
|
25
|
-
export const LBTC_EVENT_V2 = EventFragment.from(
|
|
26
|
-
'DepositToBridge(address fromAddress, bytes32 toAddress, bytes32 payloadHash)',
|
|
27
|
-
)
|
|
28
|
-
const LBTC_EVENTS_HASHES = new Set([LBTC_EVENT.topicHash, LBTC_EVENT_V2.topicHash])
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Fetch offchain token data for all transfers in request
|
|
32
|
-
*
|
|
33
|
-
* @param request - Request (or subset of) to fetch offchainTokenData for
|
|
34
|
-
* @returns Array of byte arrays, one per transfer in request
|
|
35
|
-
*/
|
|
36
|
-
export async function fetchEVMOffchainTokenData(
|
|
37
|
-
request: Pick<CCIPRequest, 'tx'> & {
|
|
38
|
-
message: CCIPMessage
|
|
39
|
-
log: Pick<CCIPRequest['log'], 'index'>
|
|
40
|
-
},
|
|
41
|
-
ctx: WithLogger,
|
|
42
|
-
): Promise<OffchainTokenData[]> {
|
|
43
|
-
const { networkType } = networkInfo(request.message.sourceChainSelector)
|
|
44
|
-
// there's a chance there are other CCIPSendRequested in same tx,
|
|
45
|
-
// and they may contain USDC transfers as well, so we select
|
|
46
|
-
// any USDC logs after that and before our CCIPSendRequested
|
|
47
|
-
const prevCcipRequestIdx =
|
|
48
|
-
request.tx.logs.find(
|
|
49
|
-
({ topics, index }) => topics[0]! in requestsFragments && index < request.log.index,
|
|
50
|
-
)?.index ?? -1
|
|
51
|
-
const usdcRequestLogs = request.tx.logs.filter(
|
|
52
|
-
({ index }) => prevCcipRequestIdx < index && index < request.log.index,
|
|
53
|
-
) as Log[]
|
|
54
|
-
|
|
55
|
-
const offchainTokenData: OffchainTokenData[] = request.message.tokenAmounts.map(
|
|
56
|
-
() => undefined, // default tokenData
|
|
57
|
-
)
|
|
58
|
-
const usdcTokenData = await getUsdcTokenData(
|
|
59
|
-
request.message.tokenAmounts,
|
|
60
|
-
usdcRequestLogs,
|
|
61
|
-
networkType,
|
|
62
|
-
ctx,
|
|
63
|
-
)
|
|
64
|
-
let lbtcTokenData: OffchainTokenData[] = []
|
|
65
|
-
try {
|
|
66
|
-
let tokenAmounts: readonly SourceTokenData[]
|
|
67
|
-
if ('sourceTokenData' in request.message) {
|
|
68
|
-
tokenAmounts = request.message.sourceTokenData.map(parseSourceTokenData)
|
|
69
|
-
} else {
|
|
70
|
-
tokenAmounts = request.message.tokenAmounts
|
|
71
|
-
}
|
|
72
|
-
//for lbtc we distinguish logs by hash in event, so we can pass all of them
|
|
73
|
-
lbtcTokenData = await getLbtcTokenData(tokenAmounts, request.tx.logs as Log[], networkType, ctx)
|
|
74
|
-
} catch (_) {
|
|
75
|
-
// pass
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
for (let i = 0; i < offchainTokenData.length; i++) {
|
|
79
|
-
if (usdcTokenData[i]) {
|
|
80
|
-
offchainTokenData[i] = usdcTokenData[i]
|
|
81
|
-
} else if (lbtcTokenData[i]) {
|
|
82
|
-
offchainTokenData[i] = lbtcTokenData[i]
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return offchainTokenData
|
|
87
|
-
}
|
|
1
|
+
import type { OffchainTokenData } from '../types.ts'
|
|
2
|
+
import { defaultAbiCoder } from './const.ts'
|
|
88
3
|
|
|
89
4
|
/**
|
|
90
5
|
* Encodes offchain token data for EVM execution.
|
|
@@ -99,107 +14,3 @@ export function encodeEVMOffchainTokenData(data: OffchainTokenData): string {
|
|
|
99
14
|
}
|
|
100
15
|
return '0x'
|
|
101
16
|
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Try to fetch USDC attestations for transfers, return undefined in position if can't
|
|
105
|
-
*
|
|
106
|
-
* @param tokenAmounts - all tokenAmounts to try
|
|
107
|
-
* @param allLogsInRequest - all other logs in same tx as CCIPSendRequested
|
|
108
|
-
* @param networkType - network type (mainnet or testnet)
|
|
109
|
-
* @returns array where each position is either the attestation for that transfer or undefined
|
|
110
|
-
**/
|
|
111
|
-
async function getUsdcTokenData(
|
|
112
|
-
tokenAmounts: CCIPMessage['tokenAmounts'],
|
|
113
|
-
allLogsInRequest: Pick<Log, 'topics' | 'address' | 'data'>[],
|
|
114
|
-
networkType: NetworkType,
|
|
115
|
-
{ logger = console }: WithLogger = {},
|
|
116
|
-
): Promise<OffchainTokenData[]> {
|
|
117
|
-
const attestations: OffchainTokenData[] = []
|
|
118
|
-
|
|
119
|
-
const messageSentPerTokenAndPool = allLogsInRequest.reduce((acc, log, i, arr) => {
|
|
120
|
-
// for our MessageSent of interest (USDC-like), the token is the contract
|
|
121
|
-
// which emitted a (burn) Transfer immediately before this event, and the pool emitted a Burned
|
|
122
|
-
// event 2 events after
|
|
123
|
-
const transferLog = arr[i - 1]
|
|
124
|
-
const poolLog = arr[i + 2]
|
|
125
|
-
if (
|
|
126
|
-
log.topics[0] !== USDC_EVENT.topicHash ||
|
|
127
|
-
transferLog?.topics[0] !== TRANSFER_EVENT.topicHash ||
|
|
128
|
-
!poolLog?.topics.length ||
|
|
129
|
-
!BURNED_EVENT_TOPIC_HASHES.has(poolLog.topics[0]!)
|
|
130
|
-
) {
|
|
131
|
-
return acc
|
|
132
|
-
}
|
|
133
|
-
const token = transferLog.address
|
|
134
|
-
const pool = poolLog.address
|
|
135
|
-
acc.set(token, [...(acc.get(token) ?? []), log])
|
|
136
|
-
acc.set(pool, [...(acc.get(pool) ?? []), log])
|
|
137
|
-
return acc
|
|
138
|
-
}, new Map<string | Addressable, (typeof allLogsInRequest)[number][]>())
|
|
139
|
-
|
|
140
|
-
for (const [i, tokenAmount] of tokenAmounts.entries()) {
|
|
141
|
-
const tokenOrPool = 'token' in tokenAmount ? tokenAmount.token : tokenAmount.sourcePoolAddress
|
|
142
|
-
|
|
143
|
-
// what if there are more USDC transfers of this same token after this one?
|
|
144
|
-
const tokenTransfersCountAfter = tokenAmounts.filter(
|
|
145
|
-
(ta, j) => ('token' in ta ? ta.token : ta.sourcePoolAddress) === tokenOrPool && j > i,
|
|
146
|
-
).length
|
|
147
|
-
|
|
148
|
-
let messageSentLog: (typeof allLogsInRequest)[number] | undefined
|
|
149
|
-
const messageSents = messageSentPerTokenAndPool.get(tokenOrPool)
|
|
150
|
-
if (messageSents) {
|
|
151
|
-
// look from the end (near our request), but skip MessageSents for further transfers
|
|
152
|
-
messageSentLog = messageSents[messageSents.length - 1 - tokenTransfersCountAfter]
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
let tokenData: OffchainTokenData
|
|
156
|
-
if (messageSentLog) {
|
|
157
|
-
let message
|
|
158
|
-
try {
|
|
159
|
-
message = defaultAbiCoder.decode(USDC_EVENT.inputs, messageSentLog.data)[0] as string
|
|
160
|
-
const attestation = await getUsdcAttestation(message, networkType)
|
|
161
|
-
tokenData = {
|
|
162
|
-
_tag: 'usdc',
|
|
163
|
-
message,
|
|
164
|
-
attestation,
|
|
165
|
-
}
|
|
166
|
-
// encoding of OffchainTokenData to be done as part of Chain.executeReceipt
|
|
167
|
-
} catch (err) {
|
|
168
|
-
// maybe not a USDC transfer, or not ready
|
|
169
|
-
logger.warn(`❌ EVM CCTP: Failed to fetch attestation for message:`, message, err)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
attestations.push(tokenData)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return attestations
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Try to fetch LBTC attestations for transfers, return undefined in position if can't or not required
|
|
180
|
-
**/
|
|
181
|
-
async function getLbtcTokenData(
|
|
182
|
-
tokenAmounts: readonly SourceTokenData[],
|
|
183
|
-
allLogsInRequest: readonly Pick<Log, 'topics' | 'address' | 'data'>[],
|
|
184
|
-
networkType: NetworkType,
|
|
185
|
-
{ logger = console }: WithLogger = {},
|
|
186
|
-
): Promise<OffchainTokenData[]> {
|
|
187
|
-
const lbtcDepositHashes = new Set(
|
|
188
|
-
allLogsInRequest
|
|
189
|
-
.filter(({ topics }) => LBTC_EVENTS_HASHES.has(topics[0]!))
|
|
190
|
-
.map(({ topics }) => topics[3]),
|
|
191
|
-
)
|
|
192
|
-
return Promise.all(
|
|
193
|
-
tokenAmounts.map(async ({ extraData }) => {
|
|
194
|
-
// Attestation is required when SourceTokenData.extraData is 32 bytes long ('0x' + 64 hex chars)
|
|
195
|
-
// otherwise attestation is not required
|
|
196
|
-
if (lbtcDepositHashes.has(extraData)) {
|
|
197
|
-
try {
|
|
198
|
-
return { _tag: 'lbtc', extraData, ...(await getLbtcAttestation(extraData, networkType)) }
|
|
199
|
-
} catch (err) {
|
|
200
|
-
logger.warn(`❌ EVM LBTC: Failed to fetch attestation for message:`, extraData, err)
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}),
|
|
204
|
-
)
|
|
205
|
-
}
|
package/src/evm/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type TransactionRequest, Result } from 'ethers'
|
|
2
2
|
|
|
3
3
|
import type { ChainFamily } from '../types.ts'
|
|
4
4
|
|
|
@@ -7,5 +7,23 @@ import type { ChainFamily } from '../types.ts'
|
|
|
7
7
|
*/
|
|
8
8
|
export type UnsignedEVMTx = {
|
|
9
9
|
family: typeof ChainFamily.EVM
|
|
10
|
-
transactions: Pick<TransactionRequest, 'from' | 'to' | 'data'>[]
|
|
10
|
+
transactions: Pick<TransactionRequest, 'from' | 'to' | 'data' | 'gasLimit'>[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Convert a Result or Promise to an object
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export function resultToObject<T>(o: T): T {
|
|
18
|
+
if (o instanceof Promise) return o.then(resultToObject) as T
|
|
19
|
+
if (!(o instanceof Result)) return o
|
|
20
|
+
if (o.length === 0) return o.toArray() as T
|
|
21
|
+
try {
|
|
22
|
+
const obj = o.toObject()
|
|
23
|
+
if (!Object.keys(obj).every((k) => /^_+\d*$/.test(k)))
|
|
24
|
+
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, resultToObject(v)])) as T
|
|
25
|
+
} catch (_) {
|
|
26
|
+
// fallthrough
|
|
27
|
+
}
|
|
28
|
+
return o.toArray().map(resultToObject) as T
|
|
11
29
|
}
|