@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.
- package/CHANGELOG.md +144 -0
- package/README.md +7 -7
- package/constants.d.ts +1 -0
- package/constants.js +1 -0
- package/index.ts +3 -0
- package/package.json +18 -4
- package/src/chains/Arbitrum.ts +14 -0
- package/src/chains/Avalanche.ts +15 -0
- package/src/chains/BNB.ts +15 -0
- package/src/chains/Base.ts +14 -0
- package/src/chains/BaseSepolia.ts +7 -0
- package/src/chains/Ethereum.ts +7 -7
- package/src/chains/Gnosis.ts +14 -0
- package/src/chains/Optimism.ts +7 -7
- package/src/chains/Polygon.ts +10 -7
- package/src/chains/Sonic.ts +13 -0
- package/src/chains/index.ts +7 -0
- package/src/context/Context.ts +102 -7
- package/src/environment.ts +150 -71
- package/src/evm.ts +5 -4
- package/src/helpers/BorshDeserializer.ts +133 -0
- package/src/helpers/consensus.ts +35 -0
- package/src/helpers/constants.ts +7 -1
- package/src/helpers/index.ts +5 -0
- package/src/helpers/math.ts +20 -0
- package/src/helpers/serialize.ts +5 -125
- package/src/helpers/strings.ts +82 -5
- package/src/intents/Call/EvmCall.ts +199 -0
- package/src/intents/Call/EvmDynamicCall.ts +272 -0
- package/src/intents/Call/SvmCall.ts +204 -0
- package/src/intents/Call/index.ts +3 -0
- package/src/intents/Intent.ts +347 -35
- package/src/intents/Operation.ts +114 -0
- package/src/intents/Swap.ts +127 -114
- package/src/intents/Transfer.ts +72 -123
- package/src/intents/index.ts +1 -0
- package/src/log.ts +83 -0
- package/src/queries/EvmCallQuery.ts +43 -0
- package/src/queries/QueryResponse.ts +26 -0
- package/src/queries/RelevantTokensQuery.ts +82 -0
- package/src/queries/SubgraphQuery.ts +50 -0
- package/src/queries/SvmAccountsInfoQuery.ts +65 -0
- package/src/queries/TokenPriceQuery.ts +47 -0
- package/src/queries/index.ts +6 -1
- package/src/storage/index.ts +1 -0
- package/src/storage/storage.ts +40 -0
- package/src/svm.ts +27 -0
- package/src/tokens/BlockchainToken.ts +108 -0
- package/src/tokens/DenominationToken.ts +70 -0
- package/src/tokens/ERC20Token.ts +192 -0
- package/src/tokens/SPLToken.ts +162 -0
- package/src/tokens/Token.ts +55 -155
- package/src/tokens/TokenAmount.ts +72 -30
- package/src/tokens/TokenProvider.ts +54 -0
- package/src/tokens/Tokens.ts +186 -0
- package/src/tokens/USD.ts +9 -6
- package/src/tokens/index.ts +6 -0
- package/src/types/Address.ts +86 -14
- package/src/types/BigInt.ts +14 -22
- package/src/types/ByteArray.ts +41 -3
- package/src/types/Bytes.ts +7 -0
- package/src/types/ChainId.ts +9 -1
- package/src/types/Option.ts +35 -0
- package/src/types/Result.ts +68 -0
- package/src/types/TriggerType.ts +4 -0
- package/src/types/evm/EvmDecodeParam.ts +7 -0
- package/src/types/evm/EvmEncodeParam.ts +31 -0
- package/src/types/evm/index.ts +2 -0
- package/src/types/index.ts +8 -2
- package/src/types/svm/SvmAccountInfo.ts +32 -0
- package/src/types/svm/SvmAccountMeta.ts +28 -0
- package/src/types/svm/SvmFindProgramAddress.ts +32 -0
- package/src/types/svm/SvmMint.ts +44 -0
- package/src/types/svm/SvmPdaSeed.ts +19 -0
- package/src/types/svm/SvmTokenMetadataData.ts +29 -0
- package/src/types/svm/index.ts +5 -0
- package/src/intents/Call.ts +0 -238
- package/src/queries/Call.ts +0 -16
- package/src/types/EvmDecodeParam.ts +0 -30
- 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
|
+
}
|
package/src/intents/Intent.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
|
54
|
-
public
|
|
55
|
-
public
|
|
56
|
-
public
|
|
57
|
-
public
|
|
58
|
-
public
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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.
|
|
69
|
-
this.
|
|
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.
|
|
72
|
-
|
|
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
|
-
|
|
385
|
+
/**
|
|
386
|
+
* Sends this intent to the execution environment.
|
|
387
|
+
*/
|
|
388
|
+
send(): void {
|
|
389
|
+
environment.sendIntent(this)
|
|
390
|
+
}
|
|
79
391
|
}
|