@mimicprotocol/lib-ts 0.0.1-rc.9 → 0.1.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/README.md +7 -7
  3. package/constants.d.ts +1 -0
  4. package/constants.js +1 -0
  5. package/index.ts +3 -0
  6. package/package.json +18 -4
  7. package/src/chains/Arbitrum.ts +14 -0
  8. package/src/chains/Avalanche.ts +15 -0
  9. package/src/chains/BNB.ts +15 -0
  10. package/src/chains/Base.ts +14 -0
  11. package/src/chains/BaseSepolia.ts +7 -0
  12. package/src/chains/Ethereum.ts +7 -7
  13. package/src/chains/Gnosis.ts +14 -0
  14. package/src/chains/Optimism.ts +7 -7
  15. package/src/chains/Polygon.ts +10 -7
  16. package/src/chains/Sonic.ts +13 -0
  17. package/src/chains/index.ts +7 -0
  18. package/src/context/Context.ts +102 -7
  19. package/src/environment.ts +150 -71
  20. package/src/evm.ts +5 -4
  21. package/src/helpers/BorshDeserializer.ts +133 -0
  22. package/src/helpers/consensus.ts +35 -0
  23. package/src/helpers/constants.ts +7 -1
  24. package/src/helpers/index.ts +5 -0
  25. package/src/helpers/math.ts +20 -0
  26. package/src/helpers/serialize.ts +5 -125
  27. package/src/helpers/strings.ts +82 -5
  28. package/src/intents/Call/EvmCall.ts +199 -0
  29. package/src/intents/Call/EvmDynamicCall.ts +272 -0
  30. package/src/intents/Call/SvmCall.ts +204 -0
  31. package/src/intents/Call/index.ts +3 -0
  32. package/src/intents/Intent.ts +347 -35
  33. package/src/intents/Operation.ts +114 -0
  34. package/src/intents/Swap.ts +127 -114
  35. package/src/intents/Transfer.ts +72 -123
  36. package/src/intents/index.ts +1 -0
  37. package/src/log.ts +83 -0
  38. package/src/queries/EvmCallQuery.ts +43 -0
  39. package/src/queries/QueryResponse.ts +26 -0
  40. package/src/queries/RelevantTokensQuery.ts +82 -0
  41. package/src/queries/SubgraphQuery.ts +50 -0
  42. package/src/queries/SvmAccountsInfoQuery.ts +65 -0
  43. package/src/queries/TokenPriceQuery.ts +47 -0
  44. package/src/queries/index.ts +6 -1
  45. package/src/storage/index.ts +1 -0
  46. package/src/storage/storage.ts +40 -0
  47. package/src/svm.ts +27 -0
  48. package/src/tokens/BlockchainToken.ts +108 -0
  49. package/src/tokens/DenominationToken.ts +70 -0
  50. package/src/tokens/ERC20Token.ts +192 -0
  51. package/src/tokens/SPLToken.ts +162 -0
  52. package/src/tokens/Token.ts +55 -155
  53. package/src/tokens/TokenAmount.ts +72 -30
  54. package/src/tokens/TokenProvider.ts +54 -0
  55. package/src/tokens/Tokens.ts +186 -0
  56. package/src/tokens/USD.ts +9 -6
  57. package/src/tokens/index.ts +6 -0
  58. package/src/types/Address.ts +86 -14
  59. package/src/types/BigInt.ts +14 -22
  60. package/src/types/ByteArray.ts +41 -3
  61. package/src/types/Bytes.ts +7 -0
  62. package/src/types/ChainId.ts +9 -1
  63. package/src/types/Option.ts +35 -0
  64. package/src/types/Result.ts +68 -0
  65. package/src/types/TriggerType.ts +4 -0
  66. package/src/types/evm/EvmDecodeParam.ts +7 -0
  67. package/src/types/evm/EvmEncodeParam.ts +31 -0
  68. package/src/types/evm/index.ts +2 -0
  69. package/src/types/index.ts +8 -2
  70. package/src/types/svm/SvmAccountInfo.ts +32 -0
  71. package/src/types/svm/SvmAccountMeta.ts +28 -0
  72. package/src/types/svm/SvmFindProgramAddress.ts +32 -0
  73. package/src/types/svm/SvmMint.ts +44 -0
  74. package/src/types/svm/SvmPdaSeed.ts +19 -0
  75. package/src/types/svm/SvmTokenMetadataData.ts +29 -0
  76. package/src/types/svm/index.ts +5 -0
  77. package/src/intents/Call.ts +0 -238
  78. package/src/queries/Call.ts +0 -16
  79. package/src/types/EvmDecodeParam.ts +0 -30
  80. package/src/types/EvmEncodeParam.ts +0 -54
@@ -0,0 +1,204 @@
1
+ import { environment } from '../../environment'
2
+ import { TokenAmount } from '../../tokens'
3
+ import { Address, Bytes, ChainId } from '../../types'
4
+ import { SvmAccountMeta } from '../../types/svm/SvmAccountMeta'
5
+ import { IntentBuilder } from '../Intent'
6
+ import { Operation, OperationBuilder, OperationEvent, OperationType } from '../Operation'
7
+
8
+ /**
9
+ * Builder for creating SVM Call intents with program call operations.
10
+ * Allows chaining multiple calls and configuring fees and settlement parameters.
11
+ */
12
+ export class SvmCallBuilder extends OperationBuilder {
13
+ protected chainId: ChainId
14
+ protected instructions: SvmInstruction[] = []
15
+
16
+ /**
17
+ * Creates a SvmCallBuilder for Solana mainnet.
18
+ * @returns A new SvmCallBuilder instance
19
+ */
20
+ static forChain(): SvmCallBuilder {
21
+ return new SvmCallBuilder()
22
+ }
23
+
24
+ /**
25
+ * Creates a new SvmCallBuilder instance.
26
+ */
27
+ private constructor() {
28
+ super()
29
+ this.chainId = ChainId.SOLANA_MAINNET
30
+ }
31
+
32
+ /**
33
+ * Adds an instruction to the intent.
34
+ * @param instruction - The instruction to add
35
+ * @returns This SvmCallBuilder instance for method chaining
36
+ */
37
+ addInstruction(instruction: SvmInstruction): SvmCallBuilder {
38
+ this.instructions.push(instruction)
39
+ return this
40
+ }
41
+
42
+ /**
43
+ * Adds multiple instructions to the intent.
44
+ * @param instructions - The instructions to add
45
+ * @returns This SvmCallBuilder instance for method chaining
46
+ */
47
+ addInstructions(instructions: SvmInstruction[]): SvmCallBuilder {
48
+ for (let i = 0; i < instructions.length; i++) this.addInstruction(instructions[i])
49
+ return this
50
+ }
51
+
52
+ /**
53
+ * Adds the instructions from another SvmCallBuilder to this SvmCallBuilder.
54
+ * @param builder - The SvmCallBuilder to add the instructions from
55
+ * @returns This SvmCallBuilder instance for method chaining
56
+ */
57
+ addInstructionsFromBuilder(builder: SvmCallBuilder): SvmCallBuilder {
58
+ return this.addInstructions(builder.getInstructions())
59
+ }
60
+
61
+ /**
62
+ * Adds the instructions from multiple SvmCallBuilders to this SvmCallBuilder.
63
+ * @param builders - The SvmCallBuilders to add the instructions from
64
+ * @returns This SvmCallBuilder instance for method chaining
65
+ */
66
+ addInstructionsFromBuilders(builders: SvmCallBuilder[]): SvmCallBuilder {
67
+ for (let i = 0; i < builders.length; i++) this.addInstructionsFromBuilder(builders[i])
68
+ return this
69
+ }
70
+
71
+ /**
72
+ * Returns a copy of the instructions array.
73
+ * @returns A copy of the instructions array
74
+ */
75
+ getInstructions(): SvmInstruction[] {
76
+ return this.instructions.slice(0)
77
+ }
78
+
79
+ /**
80
+ * Sets the user address for this intent.
81
+ * @param user - The user address
82
+ * @returns This SvmCallBuilder instance for method chaining
83
+ */
84
+ addUser(user: Address): SvmCallBuilder {
85
+ return changetype<SvmCallBuilder>(super.addUser(user))
86
+ }
87
+
88
+ /**
89
+ * Sets the user address from a string.
90
+ * @param user - The user address as a hex string
91
+ * @returns This SvmCallBuilder instance for method chaining
92
+ */
93
+ addUserAsString(user: string): SvmCallBuilder {
94
+ return changetype<SvmCallBuilder>(super.addUserAsString(user))
95
+ }
96
+
97
+ /**
98
+ * Sets an event for the intent.
99
+ * @param topic - The topic to be indexed in the event
100
+ * @param data - The event data
101
+ * @returns This SvmCallBuilder instance for method chaining
102
+ */
103
+ addEvent(topic: Bytes, data: Bytes): SvmCallBuilder {
104
+ return changetype<SvmCallBuilder>(super.addEvent(topic, data))
105
+ }
106
+
107
+ /**
108
+ * Sets multiple events for the intent.
109
+ * @param events - The list of events to be added
110
+ * @returns This SvmCallBuilder instance for method chaining
111
+ */
112
+ addEvents(events: OperationEvent[]): SvmCallBuilder {
113
+ return changetype<SvmCallBuilder>(super.addEvents(events))
114
+ }
115
+
116
+ /**
117
+ * Builds and returns the final SvmCall intent.
118
+ * @returns A new SvmCall instance with all configured parameters
119
+ */
120
+ build(): SvmCall {
121
+ return new SvmCall(this.instructions, this.user, this.events)
122
+ }
123
+
124
+ /**
125
+ * Builds this operation and sends it inside an intent with the provided fee data.
126
+ * @param maxFee - The max fee to pay for the intent
127
+ * @param feePayer - The fee payer for the intent (optional)
128
+ */
129
+ send(maxFee: TokenAmount, feePayer: Address | null = null): void {
130
+ this.build().send(maxFee, feePayer)
131
+ }
132
+ }
133
+
134
+ export class SvmInstructionBuilder {
135
+ protected programId: Address = Address.zero(32)
136
+ protected accountsMeta: SvmAccountMeta[] = []
137
+ protected data: Bytes = Bytes.empty()
138
+
139
+ setProgram(programId: Address): SvmInstructionBuilder {
140
+ this.programId = programId
141
+ return this
142
+ }
143
+
144
+ setAccounts(accountsMeta: SvmAccountMeta[]): SvmInstructionBuilder {
145
+ this.accountsMeta = accountsMeta
146
+ return this
147
+ }
148
+
149
+ setDataFromBytes(data: Bytes): SvmInstructionBuilder {
150
+ this.data = data
151
+ return this
152
+ }
153
+
154
+ setDataFromHex(data: string): SvmInstructionBuilder {
155
+ return this.setDataFromBytes(Bytes.fromHexString(data))
156
+ }
157
+
158
+ instruction(): SvmInstruction {
159
+ return new SvmInstruction(this.programId.toBase58String(), this.accountsMeta, this.data.toHexString())
160
+ }
161
+ }
162
+
163
+ @json
164
+ export class SvmInstruction {
165
+ constructor(
166
+ public programId: string,
167
+ public accountsMeta: SvmAccountMeta[],
168
+ public data: string
169
+ ) {}
170
+ }
171
+
172
+ /**
173
+ * Represents a SVM Call intent containing one or more program calls to be executed.
174
+ */
175
+ @json
176
+ export class SvmCall extends Operation {
177
+ public instructions: SvmInstruction[]
178
+
179
+ /**
180
+ * Creates a new SvmCall intent.
181
+ * @param instructions - Array of instructions to execute
182
+ * @param maxFees - The list of max fees to pay for the call intent
183
+ * @param settler - The settler address (optional)
184
+ * @param user - The user address (optional)
185
+ * @param deadline - The deadline timestamp (optional)
186
+ * @param nonce - The nonce for replay protection (optional)
187
+ */
188
+ constructor(instructions: SvmInstruction[], user: Address | null = null, events: OperationEvent[] | null = null) {
189
+ super(OperationType.SvmCall, ChainId.SOLANA_MAINNET, user, events)
190
+ if (instructions.length === 0) throw new Error('Call list cannot be empty')
191
+ this.instructions = instructions
192
+ }
193
+
194
+ /**
195
+ * Sends this SvmCall intent to the execution environment.
196
+ * @param maxFee - The max fee to pay for the intent
197
+ * @param feePayer - The fee payer for the intent (optional)
198
+ */
199
+ public send(maxFee: TokenAmount, feePayer: Address | null = null): void {
200
+ const intentBuilder = new IntentBuilder().addMaxFee(maxFee).addOperation(this)
201
+ if (feePayer) intentBuilder.addFeePayer(feePayer)
202
+ environment.sendIntent(intentBuilder.build())
203
+ }
204
+ }
@@ -0,0 +1,3 @@
1
+ export * from './EvmCall'
2
+ export * from './EvmDynamicCall'
3
+ export * from './SvmCall'
@@ -1,79 +1,391 @@
1
1
  import { environment } from '../environment'
2
2
  import { evm } from '../evm'
3
3
  import { NULL_ADDRESS } from '../helpers'
4
- import { Address, BigInt } from '../types'
4
+ import { BlockchainToken, Token, TokenAmount } from '../tokens'
5
+ import { Address, BigInt, Bytes, ChainId } from '../types'
6
+ import { SvmAccountMeta } from '../types/svm/SvmAccountMeta'
5
7
 
6
- export enum OperationType {
7
- Swap,
8
- Transfer,
9
- Call,
10
- }
8
+ import { EvmCall, EvmCallData } from './Call/EvmCall'
9
+ import { EvmDynamicArg, EvmDynamicCall, EvmDynamicCallData } from './Call/EvmDynamicCall'
10
+ import { SvmCall, SvmInstruction } from './Call/SvmCall'
11
+ import { Operation, OperationBuilder, OperationEvent, OperationType } from './Operation'
12
+ import { Swap, SwapTokenIn, SwapTokenOut } from './Swap'
13
+ import { Transfer, TransferData } from './Transfer'
11
14
 
12
15
  const DEFAULT_DEADLINE = 5 * 60 // 5 minutes in seconds
13
16
 
14
- export abstract class IntentBuilder {
15
- protected user: Address | null = null
17
+ /**
18
+ * Builder for creating intents with one or more operations.
19
+ */
20
+ export class IntentBuilder {
16
21
  protected settler: Address | null = null
22
+ protected feePayer: Address | null = null
17
23
  protected deadline: BigInt | null = null
18
24
  protected nonce: string | null = null
25
+ protected maxFees: TokenAmount[] = []
26
+ protected operations: Operation[] = []
27
+
28
+ /**
29
+ * Adds an operation to this intent.
30
+ * @param operation - The operation to add
31
+ * @returns This IntentBuilder instance for method chaining
32
+ */
33
+ addOperation(operation: Operation): IntentBuilder {
34
+ this.operations.push(operation)
35
+ return this
36
+ }
37
+
38
+ /**
39
+ * Adds multiple operations to this intent.
40
+ * @param operations - The operations to add
41
+ * @returns This IntentBuilder instance for method chaining
42
+ */
43
+ addOperations(operations: Operation[]): IntentBuilder {
44
+ for (let i = 0; i < operations.length; i++) this.addOperation(operations[i])
45
+ return this
46
+ }
47
+
48
+ /**
49
+ * Adds a built operation builder to this intent.
50
+ * @param operationBuilder - The operation builder to build and add
51
+ * @returns This IntentBuilder instance for method chaining
52
+ */
53
+ addOperationBuilder(operationBuilder: OperationBuilder): IntentBuilder {
54
+ return this.addOperation(operationBuilder.build())
55
+ }
56
+
57
+ /**
58
+ * Adds multiple built operation builders to this intent.
59
+ * @param operationBuilders - The operation builders to build and add
60
+ * @returns This IntentBuilder instance for method chaining
61
+ */
62
+ addOperationsBuilders(operationBuilders: OperationBuilder[]): IntentBuilder {
63
+ for (let i = 0; i < operationBuilders.length; i++) this.addOperationBuilder(operationBuilders[i])
64
+ return this
65
+ }
66
+
67
+ /**
68
+ * Adds a single EVM call operation to this intent from raw parameters.
69
+ * @param chainId - The blockchain network identifier
70
+ * @param target - The contract address to call
71
+ * @param data - The encoded call data
72
+ * @param value - The native token value to send
73
+ * @param user - The user that should execute the operation
74
+ * @param events - The operation events to emit
75
+ * @returns This IntentBuilder instance for method chaining
76
+ */
77
+ addEvmCallOperation(
78
+ chainId: ChainId,
79
+ target: Address,
80
+ data: Bytes = Bytes.empty(),
81
+ value: BigInt = BigInt.zero(),
82
+ user: Address | null = null,
83
+ events: OperationEvent[] | null = null
84
+ ): IntentBuilder {
85
+ return this.addOperation(new EvmCall(chainId, [new EvmCallData(target, data, value)], user, events))
86
+ }
19
87
 
88
+ /**
89
+ * Adds a single EVM dynamic call operation to this intent from raw parameters.
90
+ * @param chainId - The blockchain network identifier
91
+ * @param target - The contract address to call
92
+ * @param selector - The function selector to call
93
+ * @param args - The dynamic arguments to resolve at execution time
94
+ * @param value - The native token value to send
95
+ * @param user - The user that should execute the operation
96
+ * @param events - The operation events to emit
97
+ * @returns This IntentBuilder instance for method chaining
98
+ */
99
+ addEvmDynamicCallOperation(
100
+ chainId: ChainId,
101
+ target: Address,
102
+ selector: Bytes,
103
+ args: EvmDynamicArg[] = [],
104
+ value: BigInt = BigInt.zero(),
105
+ user: Address | null = null,
106
+ events: OperationEvent[] | null = null
107
+ ): IntentBuilder {
108
+ return this.addOperation(
109
+ new EvmDynamicCall(chainId, [new EvmDynamicCallData(target, selector, args, value)], user, events)
110
+ )
111
+ }
112
+
113
+ /**
114
+ * Adds a single swap operation to this intent from raw parameters.
115
+ * @param sourceChain - The source blockchain network identifier
116
+ * @param tokenIn - The token to swap from
117
+ * @param amountIn - The amount to swap from
118
+ * @param tokenOut - The token to receive
119
+ * @param minAmountOut - The minimum amount to receive
120
+ * @param recipient - The recipient of the output token
121
+ * @param destinationChain - The destination blockchain network identifier
122
+ * @param user - The user that should execute the operation
123
+ * @param events - The operation events to emit
124
+ * @returns This IntentBuilder instance for method chaining
125
+ */
126
+ addSwapOperation(
127
+ sourceChain: ChainId,
128
+ tokenIn: Token,
129
+ amountIn: BigInt,
130
+ tokenOut: Token,
131
+ minAmountOut: BigInt,
132
+ recipient: Address,
133
+ destinationChain: ChainId = sourceChain,
134
+ user: Address | null = null,
135
+ events: OperationEvent[] | null = null
136
+ ): IntentBuilder {
137
+ const swapIn = SwapTokenIn.fromBigInt(tokenIn, amountIn)
138
+ const swapOut = SwapTokenOut.fromBigInt(tokenOut, minAmountOut, recipient)
139
+ return this.addOperation(new Swap(sourceChain, [swapIn], [swapOut], destinationChain, user, events))
140
+ }
141
+
142
+ /**
143
+ * Adds a single transfer operation to this intent from raw parameters.
144
+ * @param token - The token to transfer
145
+ * @param amount - The amount to transfer
146
+ * @param recipient - The recipient of the transfer
147
+ * @param user - The user that should execute the operation
148
+ * @param events - The operation events to emit
149
+ * @returns This IntentBuilder instance for method chaining
150
+ */
151
+ addTransferOperation(
152
+ token: Token,
153
+ amount: BigInt,
154
+ recipient: Address,
155
+ user: Address | null = null,
156
+ events: OperationEvent[] | null = null
157
+ ): IntentBuilder {
158
+ if (!(token instanceof BlockchainToken)) throw new Error('Transfer token must be a blockchain token')
159
+ const transferAmount = TokenAmount.fromBigInt(token, amount)
160
+ const transferData = TransferData.fromTokenAmount(transferAmount, recipient)
161
+ const chainId = changetype<BlockchainToken>(token).chainId
162
+ return this.addOperation(new Transfer(chainId, [transferData], user, events))
163
+ }
164
+
165
+ /**
166
+ * Adds a single SVM call operation to this intent from raw parameters.
167
+ * @param programId - The program address to call
168
+ * @param accountsMeta - The accounts metadata for the instruction
169
+ * @param data - The encoded instruction data
170
+ * @param user - The user that should execute the operation
171
+ * @param events - The operation events to emit
172
+ * @returns This IntentBuilder instance for method chaining
173
+ */
174
+ addSvmCallOperation(
175
+ programId: Address,
176
+ accountsMeta: SvmAccountMeta[],
177
+ data: Bytes,
178
+ user: Address | null = null,
179
+ events: OperationEvent[] | null = null
180
+ ): IntentBuilder {
181
+ return this.addOperation(new SvmCall([SvmInstruction.create(programId, accountsMeta, data)], user, events))
182
+ }
183
+
184
+ /**
185
+ * Sets the settler address for this intent.
186
+ * @param settler - The settler address as an Address instance
187
+ * @returns This IntentBuilder instance for method chaining
188
+ */
20
189
  addSettler(settler: Address): IntentBuilder {
21
190
  this.settler = settler
22
191
  return this
23
192
  }
24
193
 
194
+ /**
195
+ * Sets the settler address from a string.
196
+ * @param settler - The settler address as a hex string
197
+ * @returns This IntentBuilder instance for method chaining
198
+ */
25
199
  addSettlerAsString(settler: string): IntentBuilder {
26
200
  return this.addSettler(Address.fromString(settler))
27
201
  }
28
202
 
29
- addDeadline(deadline: BigInt): IntentBuilder {
30
- this.deadline = deadline
203
+ /**
204
+ * Sets the fee payer address for this intent.
205
+ * @param feePayer - The fee payer address as an Address instance
206
+ * @returns This IntentBuilder instance for method chaining
207
+ */
208
+ addFeePayer(feePayer: Address): IntentBuilder {
209
+ this.feePayer = feePayer
31
210
  return this
32
211
  }
33
212
 
34
- addUser(user: Address): IntentBuilder {
35
- this.user = user
36
- return this
213
+ /**
214
+ * Sets the fee payer address from a string.
215
+ * @param feePayer - The fee payer address as a hex string
216
+ * @returns This IntentBuilder instance for method chaining
217
+ */
218
+ addFeePayerAsString(feePayer: string): IntentBuilder {
219
+ return this.addFeePayer(Address.fromString(feePayer))
37
220
  }
38
221
 
39
- addUserAsString(user: string): IntentBuilder {
40
- return this.addUser(Address.fromString(user))
222
+ /**
223
+ * Sets the deadline for this intent.
224
+ * @param deadline - The deadline as a timestamp
225
+ * @returns This IntentBuilder instance for method chaining
226
+ */
227
+ addDeadline(deadline: BigInt): IntentBuilder {
228
+ this.deadline = deadline
229
+ return this
41
230
  }
42
231
 
232
+ /**
233
+ * Sets the nonce for this intent.
234
+ * @param nonce - The nonce to be set for the intent
235
+ * @returns This IntentBuilder instance for method chaining
236
+ */
43
237
  addNonce(nonce: string): IntentBuilder {
44
238
  this.nonce = nonce
45
239
  return this
46
240
  }
47
241
 
48
- abstract build(): Intent
242
+ /**
243
+ * Adds a max fee for this intent.
244
+ * @param fee - The max fee token amount
245
+ * @returns This IntentBuilder instance for method chaining
246
+ */
247
+ addMaxFee(fee: TokenAmount): IntentBuilder {
248
+ this.maxFees.push(fee)
249
+ return this
250
+ }
251
+
252
+ /**
253
+ * Builds and returns the final intent.
254
+ * @returns A new intent
255
+ */
256
+ build(): Intent {
257
+ return new Intent(this.maxFees, this.settler, this.feePayer, this.deadline, this.nonce, this.operations)
258
+ }
259
+
260
+ /**
261
+ * Builds and sends the final intent.
262
+ */
263
+ send(): void {
264
+ this.build().send()
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Represents an intent max fee.
270
+ * Specifies the token address and the max amount to be paid for the intent.
271
+ */
272
+ @json
273
+ export class MaxFee {
274
+ token: string
275
+ amount: string
276
+
277
+ /**
278
+ * Creates a MaxFee from a TokenAmount.
279
+ * @param tokenAmount - The token amount to be used as max fee
280
+ * @returns A new MaxFee instance
281
+ */
282
+ static fromTokenAmount(tokenAmount: TokenAmount): MaxFee {
283
+ return new MaxFee(tokenAmount.token.address, tokenAmount.amount)
284
+ }
285
+
286
+ /**
287
+ * Creates a MaxFee from a 32-bit integer amount.
288
+ * @param token - The max fee token
289
+ * @param amount - The max fee amount
290
+ * @returns A new MaxFee instance
291
+ */
292
+ static fromI32(token: Token, amount: i32): MaxFee {
293
+ return this.fromTokenAmount(TokenAmount.fromI32(token, amount))
294
+ }
295
+
296
+ /**
297
+ * Creates a MaxFee from a BigInt amount.
298
+ * @param token - The max fee token
299
+ * @param amount - The max fee amount in the token's smallest unit
300
+ * @returns A new MaxFee instance
301
+ */
302
+ static fromBigInt(token: Token, amount: BigInt): MaxFee {
303
+ return this.fromTokenAmount(TokenAmount.fromBigInt(token, amount))
304
+ }
305
+
306
+ /**
307
+ * Creates a MaxFee from a decimal string amount.
308
+ * @param token - The max fee token
309
+ * @param amount - The max fee amount as a decimal string
310
+ * @returns A new MaxFee instance
311
+ */
312
+ static fromStringDecimal(token: Token, amount: string): MaxFee {
313
+ return this.fromTokenAmount(TokenAmount.fromStringDecimal(token, amount))
314
+ }
315
+
316
+ /**
317
+ * Creates a new MaxFee instance.
318
+ * @param token - The max fee token address
319
+ * @param amount - The max fee amount
320
+ */
321
+ constructor(token: Address, amount: BigInt) {
322
+ this.token = token.toString()
323
+ this.amount = amount.toString()
324
+ }
49
325
  }
50
326
 
51
327
  let INTENT_INDEX: u32 = 0
328
+
329
+ /**
330
+ * Represents a sendable intent containing one or more operations plus intent-level metadata.
331
+ */
52
332
  @json
53
- export abstract class Intent {
54
- public op: OperationType
55
- public settler: string
56
- public user: string
57
- public deadline: string
58
- public nonce: string
59
-
60
- protected constructor(
61
- op: OperationType,
62
- settler: Address | null,
63
- user: Address | null,
64
- deadline: BigInt | null,
65
- nonce: string | null
333
+ export class Intent {
334
+ public settler: string = ''
335
+ public feePayer: string = ''
336
+ public deadline: string = ''
337
+ public nonce: string = ''
338
+ public maxFees: MaxFee[] = []
339
+ public operations: Operation[]
340
+
341
+ /**
342
+ * Creates a new intent.
343
+ * @param maxFees - The list of max fees to pay for the intent
344
+ * @param settler - The settler address
345
+ * @param feePayer - The fee payer address
346
+ * @param deadline - The deadline timestamp
347
+ * @param nonce - The nonce for replay protection
348
+ * @param operations - The operations to execute
349
+ */
350
+ constructor(
351
+ maxFees: TokenAmount[] | null = null,
352
+ settler: Address | null = null,
353
+ feePayer: Address | null = null,
354
+ deadline: BigInt | null = null,
355
+ nonce: string | null = null,
356
+ operations: Operation[] | null = null
66
357
  ) {
67
358
  const context = environment.getContext()
68
- this.op = op
69
- this.settler = settler ? settler.toString() : context.settler.toString()
359
+ this.operations = operations || []
360
+ if (this.operations.length === 0) throw new Error('Operation list cannot be empty')
361
+
362
+ const defaultChainId = this.operations[0].chainId
363
+ for (let i = 0; i < this.operations.length; i++) {
364
+ const operation = this.operations[i]
365
+
366
+ if (operation.chainId !== defaultChainId) throw new Error('All operations must have the same chainId')
367
+
368
+ if (operation.opType === OperationType.CrossChainSwap) {
369
+ if (this.operations.length > 1) throw new Error('Cross-chain swap must be the only operation in an intent')
370
+ }
371
+ }
372
+
373
+ this.maxFees = maxFees ? maxFees.map((fee: TokenAmount) => MaxFee.fromTokenAmount(fee)) : []
374
+ this.settler = settler ? settler.toString() : context.findSettler(defaultChainId).toString()
375
+ this.feePayer = feePayer ? feePayer.toString() : context.user.toString()
70
376
  this.deadline = deadline ? deadline.toString() : (context.timestamp / 1000 + DEFAULT_DEADLINE).toString()
71
- this.user = user ? user.toString() : context.user.toString()
72
- this.nonce = nonce ? nonce : evm.keccak(`${context.configId}${context.timestamp}${++INTENT_INDEX}`)
377
+ this.nonce = nonce
378
+ ? nonce
379
+ : evm.keccak(`${context.triggerSig}${context.timestamp}${context.triggerPayload.data}${++INTENT_INDEX}`)
73
380
 
74
- if (!this.user || this.user == NULL_ADDRESS) throw new Error('A user must be specified')
75
381
  if (!this.settler || this.settler == NULL_ADDRESS) throw new Error('A settler contract must be specified')
382
+ if (!this.feePayer || this.feePayer == NULL_ADDRESS) throw new Error('A fee payer must be specified')
76
383
  }
77
384
 
78
- abstract send(): void
385
+ /**
386
+ * Sends this intent to the execution environment.
387
+ */
388
+ send(): void {
389
+ environment.sendIntent(this)
390
+ }
79
391
  }