@mayanfinance/blink-sdk 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +4 -1
- package/dist/contracts.d.ts +40 -0
- package/dist/contracts.js +160 -0
- package/dist/deposit.d.ts +7 -5
- package/dist/deposit.js +95 -64
- package/dist/gen/blink/signer/v1/signer_pb.d.ts +763 -0
- package/dist/gen/blink/signer/v1/signer_pb.js +182 -0
- package/dist/gen/blink/v1/admin_pb.d.ts +590 -20
- package/dist/gen/blink/v1/admin_pb.js +132 -37
- package/dist/gen/blink/v1/api_pb.d.ts +119 -8
- package/dist/gen/blink/v1/api_pb.js +32 -12
- package/dist/gen/blink/v1/partner_pb.d.ts +118 -0
- package/dist/gen/blink/v1/partner_pb.js +46 -21
- package/dist/gen/hular/v1/admin_pb.d.ts +1220 -0
- package/dist/gen/hular/v1/admin_pb.js +219 -0
- package/dist/gen/hular/v1/api_pb.d.ts +1755 -0
- package/dist/gen/hular/v1/api_pb.js +284 -0
- package/dist/gen/hular/v1/partner_pb.d.ts +1020 -0
- package/dist/gen/hular/v1/partner_pb.js +247 -0
- package/dist/gen/hular/v1/ratelimit_pb.d.ts +10 -0
- package/dist/gen/hular/v1/ratelimit_pb.js +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/order.d.ts +9 -5
- package/dist/order.js +34 -26
- package/dist/sui.d.ts +10 -21
- package/dist/sui.js +55 -168
- package/dist/svm.d.ts +2 -4
- package/dist/svm.js +187 -203
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/dist/sui.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { bcs } from "@mysten/sui/bcs";
|
|
2
1
|
import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
3
2
|
import { Transaction, } from "@mysten/sui/transactions";
|
|
4
|
-
import {
|
|
3
|
+
import { normalizeStructTag } from "@mysten/sui/utils";
|
|
5
4
|
export const SUI_COIN_TYPE = "0x2::sui::SUI";
|
|
6
5
|
export const isNativeSuiToken = (address) => address === SUI_COIN_TYPE;
|
|
7
6
|
const client = (rpcUrl) => new SuiGrpcClient({ network: "mainnet", baseUrl: rpcUrl });
|
|
@@ -86,183 +85,62 @@ export const sponsorSuiTransaction = async (rpcUrl, transaction, sponsor, maxGas
|
|
|
86
85
|
transaction.setGasBudget(needed < maxGasBudget ? needed : maxGasBudget);
|
|
87
86
|
return Transaction.from(await transaction.build({ client: rpc }));
|
|
88
87
|
};
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
? { $kind: "Result", Result: swap.coinOutCommand }
|
|
96
|
-
: {
|
|
97
|
-
$kind: "NestedResult",
|
|
98
|
-
NestedResult: [swap.coinOutCommand, swap.coinOutResult],
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
const inputKind = (input) => input.$kind === "Object" ? input.Object.$kind : input.$kind;
|
|
102
|
-
const commandArguments = (command) => {
|
|
103
|
-
switch (command.$kind) {
|
|
104
|
-
case "MoveCall":
|
|
105
|
-
return command.MoveCall.arguments;
|
|
106
|
-
case "TransferObjects":
|
|
107
|
-
return [
|
|
108
|
-
...command.TransferObjects.objects,
|
|
109
|
-
command.TransferObjects.address,
|
|
110
|
-
];
|
|
111
|
-
case "SplitCoins":
|
|
112
|
-
return [command.SplitCoins.coin, ...command.SplitCoins.amounts];
|
|
113
|
-
case "MergeCoins":
|
|
114
|
-
return [command.MergeCoins.destination, ...command.MergeCoins.sources];
|
|
115
|
-
case "MakeMoveVec":
|
|
116
|
-
return command.MakeMoveVec.elements;
|
|
117
|
-
default:
|
|
118
|
-
return rejectSwap(`command ${command.$kind} is not allowed`);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
const referencedCommand = (arg) => arg.$kind === "Result"
|
|
122
|
-
? arg.Result
|
|
123
|
-
: arg.$kind === "NestedResult"
|
|
124
|
-
? arg.NestedResult[0]
|
|
125
|
-
: undefined;
|
|
126
|
-
const isSenderInput = (fragment, arg, sender) => {
|
|
127
|
-
if (arg.$kind !== "Input") {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
const input = fragment.inputs[arg.Input];
|
|
131
|
-
if (input?.$kind !== "Pure") {
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
const bytes = fromBase64(input.Pure.bytes);
|
|
135
|
-
return (bytes.length === 32 &&
|
|
136
|
-
normalizeSuiAddress(toHex(bytes)) === normalizeSuiAddress(sender));
|
|
137
|
-
};
|
|
138
|
-
const isCoinInStandIn = (command, srcToken) => command?.$kind === "MoveCall" &&
|
|
139
|
-
normalizeSuiAddress(command.MoveCall.package) ===
|
|
140
|
-
normalizeSuiAddress("0x2") &&
|
|
141
|
-
command.MoveCall.module === "coin" &&
|
|
142
|
-
command.MoveCall.function === "zero" &&
|
|
143
|
-
command.MoveCall.arguments.length === 0 &&
|
|
144
|
-
command.MoveCall.typeArguments.length === 1 &&
|
|
145
|
-
normalizeStructTag(command.MoveCall.typeArguments[0]) ===
|
|
146
|
-
normalizeStructTag(srcToken);
|
|
147
|
-
export const checkSuiSwapFragment = (fragment, coinOut, rules) => {
|
|
148
|
-
if (!isCoinInStandIn(fragment.commands[0], rules.srcToken)) {
|
|
149
|
-
rejectSwap("first command is not the input coin stand-in");
|
|
150
|
-
}
|
|
151
|
-
for (const input of fragment.inputs) {
|
|
152
|
-
if (input.$kind !== "Pure" &&
|
|
153
|
-
!(input.$kind === "Object" && input.Object.$kind === "SharedObject")) {
|
|
154
|
-
rejectSwap(`input ${inputKind(input)} is not allowed`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
fragment.commands.forEach((command, index) => {
|
|
158
|
-
if (index === 0) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
for (const arg of commandArguments(command)) {
|
|
162
|
-
if (arg.$kind === "GasCoin") {
|
|
163
|
-
rejectSwap("gas coin is not allowed");
|
|
164
|
-
}
|
|
165
|
-
if (arg.$kind === "Input" && arg.Input >= fragment.inputs.length) {
|
|
166
|
-
rejectSwap("argument references a missing input");
|
|
167
|
-
}
|
|
168
|
-
if (arg.$kind === "NestedResult" && arg.NestedResult[0] === 0) {
|
|
169
|
-
rejectSwap("nested result of the input coin stand-in");
|
|
170
|
-
}
|
|
171
|
-
const target = referencedCommand(arg);
|
|
172
|
-
if (target !== undefined && target >= index) {
|
|
173
|
-
rejectSwap("argument references a later command");
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (command.$kind === "TransferObjects" &&
|
|
177
|
-
!isSenderInput(fragment, command.TransferObjects.address, rules.sender)) {
|
|
178
|
-
rejectSwap("transfer recipient is not the sender");
|
|
179
|
-
}
|
|
88
|
+
const SOURCE_SWAP_WINDOW_MS = 300000n;
|
|
89
|
+
const SOURCE_SWAP_ALLOWANCE_NAME = "blink source swap";
|
|
90
|
+
export const suiSourceSwapExpiry = async (rpcUrl) => {
|
|
91
|
+
const { response } = await client(rpcUrl).ledgerService.getCheckpoint({
|
|
92
|
+
checkpointId: { oneofKind: undefined },
|
|
93
|
+
readMask: { paths: ["summary.timestamp"] },
|
|
180
94
|
});
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
outCommand >= fragment.commands.length) {
|
|
185
|
-
rejectSwap("output coin does not reference a swap command");
|
|
95
|
+
const timestamp = response.checkpoint?.summary?.timestamp;
|
|
96
|
+
if (!timestamp) {
|
|
97
|
+
throw new Error("sui checkpoint has no timestamp");
|
|
186
98
|
}
|
|
99
|
+
const nowMs = timestamp.seconds * 1000n + BigInt(Math.floor(timestamp.nanos / 1_000_000));
|
|
100
|
+
return nowMs + SOURCE_SWAP_WINDOW_MS;
|
|
187
101
|
};
|
|
188
|
-
export const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const resolve = (arg) => {
|
|
200
|
-
switch (arg.$kind) {
|
|
201
|
-
case "Input":
|
|
202
|
-
return inputs[arg.Input];
|
|
203
|
-
case "Result":
|
|
204
|
-
return arg.Result === 0 ? payment : results[arg.Result];
|
|
205
|
-
case "NestedResult":
|
|
206
|
-
return results[arg.NestedResult[0]][arg.NestedResult[1]];
|
|
207
|
-
default:
|
|
208
|
-
return rejectSwap("gas coin is not allowed");
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
fragment.commands.forEach((command, index) => {
|
|
212
|
-
if (index === 0) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
switch (command.$kind) {
|
|
216
|
-
case "MoveCall":
|
|
217
|
-
results[index] = tx.moveCall({
|
|
218
|
-
target: `${command.MoveCall.package}::${command.MoveCall.module}::${command.MoveCall.function}`,
|
|
219
|
-
typeArguments: command.MoveCall.typeArguments,
|
|
220
|
-
arguments: command.MoveCall.arguments.map(resolve),
|
|
221
|
-
});
|
|
222
|
-
return;
|
|
223
|
-
case "TransferObjects":
|
|
224
|
-
results[index] = tx.transferObjects(command.TransferObjects.objects.map(resolve), resolve(command.TransferObjects.address));
|
|
225
|
-
return;
|
|
226
|
-
case "SplitCoins":
|
|
227
|
-
results[index] = tx.splitCoins(resolve(command.SplitCoins.coin), command.SplitCoins.amounts.map(resolve));
|
|
228
|
-
return;
|
|
229
|
-
case "MergeCoins":
|
|
230
|
-
results[index] = tx.mergeCoins(resolve(command.MergeCoins.destination), command.MergeCoins.sources.map(resolve));
|
|
231
|
-
return;
|
|
232
|
-
case "MakeMoveVec":
|
|
233
|
-
results[index] = tx.makeMoveVec({
|
|
234
|
-
type: command.MakeMoveVec.type ?? undefined,
|
|
235
|
-
elements: command.MakeMoveVec.elements.map(resolve),
|
|
236
|
-
});
|
|
237
|
-
return;
|
|
238
|
-
default:
|
|
239
|
-
rejectSwap(`command ${command.$kind} is not allowed`);
|
|
240
|
-
}
|
|
102
|
+
export const addSuiSourceSwapOpenCall = (tx, call) => {
|
|
103
|
+
if (call.payment) {
|
|
104
|
+
tx.moveCall({
|
|
105
|
+
target: "0x2::coin::send_funds",
|
|
106
|
+
typeArguments: [call.srcToken],
|
|
107
|
+
arguments: [call.payment, tx.pure.address(call.sender)],
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const noRateLimit = tx.moveCall({
|
|
111
|
+
target: "0x1::option::none",
|
|
112
|
+
typeArguments: ["0x2::allowance::RateLimit"],
|
|
241
113
|
});
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
114
|
+
const proposal = tx.moveCall({
|
|
115
|
+
target: "0x2::allowance::propose_for_app",
|
|
116
|
+
typeArguments: [
|
|
117
|
+
`0x2::balance::Balance<${call.srcToken}>`,
|
|
118
|
+
`${call.packageId}::blink::SourceSwapFunding`,
|
|
119
|
+
],
|
|
120
|
+
arguments: [
|
|
121
|
+
tx.pure.string(SOURCE_SWAP_ALLOWANCE_NAME),
|
|
122
|
+
tx.pure.address(call.swapExecutor),
|
|
123
|
+
tx.pure.option("u256", call.amountIn),
|
|
124
|
+
tx.pure.option("u64", null),
|
|
125
|
+
tx.pure.option("u64", call.expiresAtMs),
|
|
126
|
+
noRateLimit,
|
|
127
|
+
],
|
|
249
128
|
});
|
|
250
|
-
const bridged = appendSwapFragment(tx, fragment, call.payment, coinOut);
|
|
251
129
|
tx.moveCall({
|
|
252
|
-
target: `${call.packageId}::blink::
|
|
130
|
+
target: `${call.packageId}::blink::open_source_swap`,
|
|
253
131
|
typeArguments: [call.srcToken, call.bridgeToken],
|
|
254
132
|
arguments: [
|
|
255
133
|
tx.object(call.escrowObject),
|
|
134
|
+
proposal,
|
|
256
135
|
tx.pure.vector("u8", hexBytes(call.quoteHash)),
|
|
257
|
-
bridged,
|
|
258
|
-
tx.pure.u64(call.amountIn),
|
|
259
136
|
tx.pure.u64(call.minBridgeOut),
|
|
137
|
+
tx.object.clock(),
|
|
260
138
|
],
|
|
261
139
|
});
|
|
262
140
|
};
|
|
263
141
|
const isSuiCoinType = (coinType) => normalizeStructTag(coinType) === normalizeStructTag(SUI_COIN_TYPE);
|
|
264
|
-
const addPayment = async (tx, rpcUrl, owner, coinType, amount) => {
|
|
265
|
-
if (isSuiCoinType(coinType)) {
|
|
142
|
+
const addPayment = async (tx, rpcUrl, owner, coinType, amount, gasless) => {
|
|
143
|
+
if (isSuiCoinType(coinType) && !gasless) {
|
|
266
144
|
const [payment] = tx.splitCoins(tx.gas, [amount]);
|
|
267
145
|
return payment;
|
|
268
146
|
}
|
|
@@ -274,20 +152,29 @@ const addPayment = async (tx, rpcUrl, owner, coinType, amount) => {
|
|
|
274
152
|
const [payment] = tx.splitCoins(primary, [amount]);
|
|
275
153
|
return payment;
|
|
276
154
|
};
|
|
277
|
-
|
|
155
|
+
const suiAddressBalance = async (rpcUrl, owner, coinType) => {
|
|
156
|
+
const { balance } = await client(rpcUrl).getBalance({ owner, coinType });
|
|
157
|
+
return BigInt(balance.addressBalance);
|
|
158
|
+
};
|
|
159
|
+
export const buildSuiSourceSwapOpen = async (request) => {
|
|
278
160
|
const tx = new Transaction();
|
|
279
161
|
tx.setSender(request.owner);
|
|
280
|
-
const
|
|
281
|
-
|
|
162
|
+
const shortfall = request.amountIn -
|
|
163
|
+
(await suiAddressBalance(request.rpcUrl, request.owner, request.srcToken));
|
|
164
|
+
const payment = shortfall > 0n
|
|
165
|
+
? await addPayment(tx, request.rpcUrl, request.owner, request.srcToken, shortfall, request.gasless)
|
|
166
|
+
: undefined;
|
|
167
|
+
addSuiSourceSwapOpenCall(tx, {
|
|
282
168
|
packageId: request.packageId,
|
|
283
169
|
escrowObject: request.escrowObject,
|
|
170
|
+
swapExecutor: request.swapExecutor,
|
|
284
171
|
sender: request.owner,
|
|
285
172
|
srcToken: request.srcToken,
|
|
286
173
|
bridgeToken: request.bridgeToken,
|
|
287
174
|
amountIn: request.amountIn,
|
|
288
175
|
minBridgeOut: request.minBridgeOut,
|
|
289
176
|
quoteHash: request.quoteHash,
|
|
290
|
-
|
|
177
|
+
expiresAtMs: await suiSourceSwapExpiry(request.rpcUrl),
|
|
291
178
|
payment,
|
|
292
179
|
});
|
|
293
180
|
return tx;
|
package/dist/svm.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AddressLookupTableAccount, PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
2
2
|
import type { SvmSwapInstructions } from "./gen/blink/v1/api_pb.js";
|
|
3
|
-
export declare const DEFAULT_SWAP_PROGRAMS: PublicKey[];
|
|
4
3
|
export declare const isNativeSvmToken: (address: string) => boolean;
|
|
4
|
+
export declare const svmSwapAuthority: (programId: PublicKey, owner: PublicKey, quoteHash: string) => PublicKey;
|
|
5
5
|
export declare const svmBalance: (rpcUrl: string, token: string, owner: string) => Promise<bigint>;
|
|
6
6
|
export interface SvmDepositRequest {
|
|
7
7
|
rpcUrl: string;
|
|
@@ -13,10 +13,8 @@ export interface SvmDepositRequest {
|
|
|
13
13
|
computeUnitPriceMicroLamports: bigint;
|
|
14
14
|
feePayer?: string;
|
|
15
15
|
}
|
|
16
|
-
export declare const resolveSwapPrograms: (chain: string, swap: SvmSwapInstructions, expectedSigner: string | undefined) => PublicKey[];
|
|
17
16
|
export interface SvmSwapDepositRequest {
|
|
18
17
|
rpcUrl: string;
|
|
19
|
-
chain: string;
|
|
20
18
|
programId: string;
|
|
21
19
|
owner: string;
|
|
22
20
|
srcToken: string;
|
|
@@ -26,7 +24,7 @@ export interface SvmSwapDepositRequest {
|
|
|
26
24
|
quoteHash: string;
|
|
27
25
|
swap: SvmSwapInstructions;
|
|
28
26
|
computeUnitPriceMicroLamports: bigint;
|
|
29
|
-
|
|
27
|
+
swapPrograms: string[];
|
|
30
28
|
}
|
|
31
29
|
export interface SvmDepositInstructions {
|
|
32
30
|
instructions: TransactionInstruction[];
|