@vleap/warps-adapter-fastset 0.1.0-alpha.2 → 0.1.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,227 +1,355 @@
1
1
  // src/constants.ts
2
2
  var WarpFastsetConstants = {
3
- ChainName: "fastset",
4
- ChainPrefix: "fastset",
5
- Pi: {
6
- Identifier: "PI",
7
- DisplayName: "Pi",
8
- Decimals: 18
9
- },
10
- GasLimit: {
11
- Default: 21e3,
12
- ContractCall: 1e5,
13
- ContractDeploy: 5e5,
14
- Transfer: 21e3,
15
- Approve: 46e3,
16
- Swap: 2e5
17
- },
18
- GasPrice: {
19
- Default: "20000000000",
20
- // 20 gwei
21
- Low: "10000000000",
22
- // 10 gwei
23
- Medium: "20000000000",
24
- // 20 gwei
25
- High: "50000000000"
26
- // 50 gwei
27
- },
28
- Network: {
29
- Mainnet: {
30
- ChainId: "1",
31
- Name: "Fastset Mainnet",
32
- BlockTime: 12
33
- },
34
- Testnet: {
35
- ChainId: "11155111",
36
- Name: "Fastset Testnet",
37
- BlockTime: 12
38
- },
39
- Devnet: {
40
- ChainId: "1337",
41
- Name: "Fastset Devnet",
42
- BlockTime: 12
43
- }
44
- },
45
- Validation: {
46
- AddressLength: 42,
47
- HexPrefix: "0x",
48
- MinGasLimit: 21e3,
49
- MaxGasLimit: 3e7
50
- },
51
- Timeouts: {
52
- DefaultRpcTimeout: 3e4,
53
- // 30 seconds
54
- GasEstimationTimeout: 1e4,
55
- // 10 seconds
56
- QueryTimeout: 15e3
57
- // 15 seconds
58
- }
3
+ // Placeholder for future FastSet-specific constants
59
4
  };
60
5
 
61
- // src/WarpFastsetBuilder.ts
62
- var WarpFastsetBuilder = class {
63
- constructor(config) {
64
- this.config = config;
65
- this.warp = {};
66
- this.actions = [];
67
- }
68
- async createFromRaw(encoded) {
69
- try {
70
- const parsed = JSON.parse(encoded);
71
- this.warp = parsed;
72
- this.actions = parsed.actions || [];
73
- return this.build();
74
- } catch (error) {
75
- throw new Error(`Failed to parse Fastset warp data: ${error}`);
6
+ // src/main.ts
7
+ import { WarpChainName } from "@vleap/warps";
8
+
9
+ // src/WarpFastsetDataLoader.ts
10
+ import * as bech323 from "bech32";
11
+
12
+ // src/sdk/FastsetClient.ts
13
+ import { bcs } from "@mysten/bcs";
14
+ import * as bech32 from "bech32";
15
+ var bcsTransaction = bcs.struct("Transaction", {
16
+ sender: bcs.fixedArray(32, bcs.u8()),
17
+ recipient: bcs.enum("Address", {
18
+ External: bcs.fixedArray(32, bcs.u8()),
19
+ FastSet: bcs.fixedArray(32, bcs.u8())
20
+ }),
21
+ nonce: bcs.u64(),
22
+ timestamp_nanos: bcs.u128(),
23
+ claim: bcs.enum("ClaimType", {
24
+ Transfer: bcs.struct("Transfer", {
25
+ recipient: bcs.enum("Address", {
26
+ External: bcs.fixedArray(32, bcs.u8()),
27
+ FastSet: bcs.fixedArray(32, bcs.u8())
28
+ }),
29
+ amount: bcs.string(),
30
+ user_data: bcs.option(bcs.fixedArray(32, bcs.u8()))
31
+ }),
32
+ TokenTransfer: bcs.struct("TokenTransfer", {
33
+ token_id: bcs.fixedArray(32, bcs.u8()),
34
+ amount: bcs.string(),
35
+ user_data: bcs.option(bcs.fixedArray(32, bcs.u8()))
36
+ }),
37
+ TokenCreation: bcs.struct("TokenCreation", {
38
+ token_name: bcs.string(),
39
+ decimals: bcs.u8(),
40
+ initial_amount: bcs.string(),
41
+ mints: bcs.vector(bcs.fixedArray(32, bcs.u8())),
42
+ user_data: bcs.option(bcs.fixedArray(32, bcs.u8()))
43
+ }),
44
+ TokenManagement: bcs.struct("TokenManagement", {
45
+ token_id: bcs.fixedArray(32, bcs.u8()),
46
+ update_id: bcs.u64(),
47
+ new_admin: bcs.option(bcs.fixedArray(32, bcs.u8())),
48
+ mints: bcs.vector(
49
+ bcs.tuple([
50
+ bcs.enum("AddressChange", {
51
+ Add: bcs.fixedArray(32, bcs.u8()),
52
+ Remove: bcs.fixedArray(32, bcs.u8())
53
+ }),
54
+ bcs.fixedArray(32, bcs.u8())
55
+ ])
56
+ ),
57
+ user_data: bcs.option(bcs.fixedArray(32, bcs.u8()))
58
+ }),
59
+ Mint: bcs.struct("Mint", {
60
+ token_id: bcs.fixedArray(32, bcs.u8()),
61
+ amount: bcs.string()
62
+ }),
63
+ ExternalClaim: bcs.struct("ExternalClaim", {
64
+ claim: bcs.struct("ExternalClaimBody", {
65
+ verifier_committee: bcs.vector(bcs.fixedArray(32, bcs.u8())),
66
+ verifier_quorum: bcs.u64(),
67
+ claim_data: bcs.vector(bcs.u8())
68
+ }),
69
+ signatures: bcs.vector(bcs.tuple([bcs.fixedArray(32, bcs.u8()), bcs.fixedArray(64, bcs.u8())]))
70
+ })
71
+ })
72
+ });
73
+ var FastsetClient = class {
74
+ constructor(config, chain) {
75
+ if (config && "proxyUrl" in config) {
76
+ this.apiUrl = config.proxyUrl;
77
+ } else if (config && chain) {
78
+ this.apiUrl = chain.defaultApiUrl;
79
+ } else {
80
+ this.apiUrl = "https://rpc.fastset.xyz";
81
+ }
82
+ }
83
+ async makeRequest(method, params = {}) {
84
+ const response = await fetch(this.apiUrl, {
85
+ method: "POST",
86
+ headers: {
87
+ "Content-Type": "application/json"
88
+ },
89
+ body: JSON.stringify({
90
+ jsonrpc: "2.0",
91
+ method,
92
+ params,
93
+ id: Date.now()
94
+ })
95
+ });
96
+ if (!response.ok) {
97
+ throw new Error(`HTTP error! status: ${response.status}`);
98
+ }
99
+ const jsonResponse = await response.json();
100
+ if (jsonResponse.error) {
101
+ throw new Error(`JSON-RPC error ${jsonResponse.error.code}: ${jsonResponse.error.message}`);
76
102
  }
103
+ return jsonResponse.result;
77
104
  }
78
- setTitle(title) {
79
- this.warp.title = title;
80
- return this;
105
+ async getAccountInfo(address, token_balance_filter, certificate_by_nonce) {
106
+ return this.makeRequest("set_getAccountInfo", {
107
+ address,
108
+ token_balance_filter,
109
+ certificate_by_nonce
110
+ });
81
111
  }
82
- setDescription(description) {
83
- this.warp.description = description;
84
- return this;
112
+ async getTokenInfo(token_ids) {
113
+ return this.makeRequest("set_getTokenInfo", {
114
+ token_ids
115
+ });
85
116
  }
86
- setPreview(preview) {
87
- this.warp.preview = preview;
88
- return this;
117
+ async getTransfers(page) {
118
+ return this.makeRequest("set_getTransfers", { page });
89
119
  }
90
- setActions(actions) {
91
- this.actions = actions;
92
- return this;
120
+ async getClaims(confirmed, page) {
121
+ return this.makeRequest("set_getClaims", { confirmed, page });
93
122
  }
94
- addAction(action) {
95
- this.actions.push(action);
96
- return this;
123
+ async getClaimsByAddress(address, page) {
124
+ return this.makeRequest("set_getClaimsByAddress", {
125
+ address,
126
+ page
127
+ });
97
128
  }
98
- async build() {
99
- return {
100
- protocol: "warp",
101
- name: this.warp.name || "fastset-warp",
102
- title: this.warp.title || "",
103
- description: this.warp.description || null,
104
- preview: this.warp.preview || null,
105
- actions: this.actions,
106
- meta: {
107
- chain: "fastset",
108
- hash: this.generateHash(this.warp.title || ""),
109
- creator: this.config.user?.wallets?.fastset || "",
110
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
111
- }
112
- };
129
+ async getNextNonce(address) {
130
+ if (typeof address === "string") {
131
+ const addressBytes = this.addressToBytes(address);
132
+ const accountInfo2 = await this.getAccountInfo(addressBytes);
133
+ return accountInfo2.next_nonce;
134
+ }
135
+ const accountInfo = await this.getAccountInfo(address);
136
+ return accountInfo.next_nonce;
113
137
  }
114
- createInscriptionTransaction(warp) {
115
- return {
116
- type: "fastset-inscription",
117
- data: JSON.stringify(warp)
118
- // TODO: Add Fastset-specific transaction fields
119
- };
138
+ async submitTransaction(transaction, signature) {
139
+ const signatureArray = Array.isArray(signature) ? signature : Array.from(signature);
140
+ return this.makeRequest("set_submitTransaction", {
141
+ transaction,
142
+ signature: signatureArray
143
+ });
120
144
  }
121
- async createFromTransaction(tx, validate = true) {
145
+ addressToBytes(address) {
122
146
  try {
123
- const warpData = tx.data || tx.payload || tx.content;
124
- if (!warpData) {
125
- throw new Error("No warp data found in transaction");
147
+ const decoded = bech32.bech32m.decode(address);
148
+ return Array.from(bech32.bech32m.fromWords(decoded.words));
149
+ } catch {
150
+ try {
151
+ const decoded = bech32.bech32.decode(address);
152
+ return Array.from(bech32.bech32.fromWords(decoded.words));
153
+ } catch {
154
+ throw new Error(`Invalid FastSet address: ${address}`);
126
155
  }
127
- const parsed = typeof warpData === "string" ? JSON.parse(warpData) : warpData;
128
- if (validate) {
129
- this.validateWarp(parsed);
130
- }
131
- return parsed;
132
- } catch (error) {
133
- throw new Error(`Failed to create warp from Fastset transaction: ${error}`);
134
156
  }
135
157
  }
136
- async createFromTransactionHash(hash, cache) {
158
+ };
159
+
160
+ // src/WarpFastsetDataLoader.ts
161
+ var WarpFastsetDataLoader = class {
162
+ constructor(config, chain) {
163
+ this.config = config;
164
+ this.chain = chain;
165
+ this.client = new FastsetClient(config, chain);
166
+ }
167
+ addressToBytes(address) {
137
168
  try {
138
- const tx = await this.fetchTransaction(hash);
139
- if (!tx) {
140
- return null;
169
+ const decoded = bech323.bech32m.decode(address);
170
+ return Array.from(bech323.bech32m.fromWords(decoded.words));
171
+ } catch {
172
+ try {
173
+ const decoded = bech323.bech32.decode(address);
174
+ return Array.from(bech323.bech32.fromWords(decoded.words));
175
+ } catch {
176
+ throw new Error(`Invalid FastSet address: ${address}`);
141
177
  }
142
- return this.createFromTransaction(tx);
143
- } catch (error) {
144
- console.error(`Failed to create warp from Fastset transaction hash: ${error}`);
145
- return null;
146
- }
147
- }
148
- generateHash(data) {
149
- let hash = 0;
150
- for (let i = 0; i < data.length; i++) {
151
- const char = data.charCodeAt(i);
152
- hash = (hash << 5) - hash + char;
153
- hash = hash & hash;
154
178
  }
155
- return hash.toString(16);
156
179
  }
157
- validateWarp(warp) {
158
- if (!warp.title) {
159
- throw new Error("Warp must have a title");
160
- }
161
- if (!warp.actions || !Array.isArray(warp.actions)) {
162
- throw new Error("Warp must have actions array");
180
+ async getAccount(address) {
181
+ const addressBytes = this.addressToBytes(address);
182
+ const accountInfo = await this.client.getAccountInfo(addressBytes);
183
+ return { chain: this.chain.name, address, balance: BigInt(accountInfo.balance) };
184
+ }
185
+ async getAccountAssets(address) {
186
+ const addressBytes = this.addressToBytes(address);
187
+ const accountInfo = await this.client.getAccountInfo(addressBytes);
188
+ const assets = [];
189
+ const balance = BigInt(accountInfo.balance);
190
+ if (balance > 0n) {
191
+ assets.push({ ...this.chain.nativeToken, amount: balance });
192
+ }
193
+ for (const [tokenId, tokenBalance] of accountInfo.token_balance) {
194
+ const amount = BigInt(tokenBalance);
195
+ if (amount > 0n) {
196
+ const tokenInfo = await this.client.getTokenInfo([tokenId]);
197
+ const metadata = tokenInfo.requested_token_metadata[0]?.[1];
198
+ assets.push({
199
+ chain: this.chain.name,
200
+ identifier: Buffer.from(tokenId).toString("hex"),
201
+ symbol: metadata?.token_name || "UNKNOWN",
202
+ name: metadata?.token_name || "Unknown Token",
203
+ decimals: metadata?.decimals || 6,
204
+ logoUrl: void 0,
205
+ amount
206
+ });
207
+ }
163
208
  }
209
+ return assets;
164
210
  }
165
- async fetchTransaction(hash) {
166
- const response = await fetch(`${this.getApiUrl()}/transaction/${hash}`);
167
- if (!response.ok) {
211
+ async getAsset(identifier) {
212
+ const tokenId = Buffer.from(identifier, "hex");
213
+ const tokenInfo = await this.client.getTokenInfo([Array.from(tokenId)]);
214
+ const metadata = tokenInfo.requested_token_metadata[0]?.[1];
215
+ if (!metadata) {
168
216
  return null;
169
217
  }
170
- return response.json();
218
+ return {
219
+ chain: this.chain.name,
220
+ identifier,
221
+ symbol: metadata.token_name,
222
+ name: metadata.token_name,
223
+ decimals: metadata.decimals,
224
+ logoUrl: void 0,
225
+ amount: BigInt(metadata.total_supply)
226
+ };
171
227
  }
172
- getApiUrl() {
173
- return "https://api.fastset.xyz";
228
+ async getAction(identifier, awaitCompleted = false) {
229
+ return null;
230
+ }
231
+ async getAccountActions(address, options) {
232
+ return [];
174
233
  }
175
234
  };
176
235
 
177
236
  // src/WarpFastsetExecutor.ts
237
+ import * as ed25519 from "@noble/ed25519";
178
238
  import {
239
+ getProviderUrl,
179
240
  getWarpActionByIndex
180
241
  } from "@vleap/warps";
181
242
 
182
- // src/config.ts
183
- var FASTSET_CHAIN_CONFIGS = {
184
- fastset: {
185
- mainnet: {
186
- apiUrl: "https://mainnet.fastset.com/api",
187
- explorerUrl: "https://explorer.fastset.com",
188
- chainId: "1",
189
- registryAddress: "0x0000000000000000000000000000000000000000",
190
- nativeToken: "PI",
191
- blockTime: 12
192
- },
193
- testnet: {
194
- apiUrl: "https://testnet.fastset.com/api",
195
- explorerUrl: "https://testnet-explorer.fastset.com",
196
- chainId: "11155111",
197
- registryAddress: "0x0000000000000000000000000000000000000000",
198
- nativeToken: "PI",
199
- blockTime: 12
200
- },
201
- devnet: {
202
- apiUrl: "http://localhost:8545",
203
- explorerUrl: "http://localhost:4000",
204
- chainId: "1337",
205
- registryAddress: "0x0000000000000000000000000000000000000000",
206
- nativeToken: "PI",
207
- blockTime: 12
208
- }
243
+ // src/sdk/Wallet.ts
244
+ import * as bech325 from "bech32";
245
+
246
+ // src/sdk/ed25519-setup.ts
247
+ import * as ed from "@noble/ed25519";
248
+ import { sha512 } from "@noble/hashes/sha512";
249
+ if (ed.etc) {
250
+ ed.etc.sha512Sync = (...m) => sha512(ed.etc.concatBytes(...m));
251
+ }
252
+
253
+ // src/sdk/Transaction.ts
254
+ var Transaction = class _Transaction {
255
+ constructor(sender, recipient, nonce, claim, options = {}) {
256
+ this.sender = sender;
257
+ this.recipient = recipient;
258
+ this.nonce = nonce;
259
+ this.claim = claim;
260
+ this.timestamp = options.timestamp ?? BigInt(Date.now()) * 1000000n;
261
+ }
262
+ toTransaction() {
263
+ return {
264
+ sender: this.sender,
265
+ recipient: this.recipient,
266
+ nonce: this.nonce,
267
+ timestamp_nanos: this.timestamp,
268
+ claim: this.claim
269
+ };
209
270
  }
210
- };
211
- var DEFAULT_CHAIN = "fastset";
212
- var getFastsetChainConfig = (chain = DEFAULT_CHAIN, env) => {
213
- const chainConfigs = FASTSET_CHAIN_CONFIGS[chain];
214
- if (!chainConfigs) {
215
- throw new Error(`Unsupported Fastset chain: ${chain}`);
271
+ getSender() {
272
+ return this.sender;
216
273
  }
217
- const config = chainConfigs[env];
218
- if (!config) {
219
- throw new Error(`Unsupported environment ${env} for chain ${chain}`);
274
+ getRecipient() {
275
+ return this.recipient;
276
+ }
277
+ getNonce() {
278
+ return this.nonce;
279
+ }
280
+ getClaim() {
281
+ return this.claim;
282
+ }
283
+ getTimestamp() {
284
+ return this.timestamp;
285
+ }
286
+ static fromTransaction(transaction) {
287
+ return new _Transaction(transaction.sender, transaction.recipient, transaction.nonce, transaction.claim, {
288
+ timestamp: transaction.timestamp_nanos
289
+ });
220
290
  }
221
- return config;
222
291
  };
223
- var getFastsetApiUrl = (env, chain = DEFAULT_CHAIN) => {
224
- return getFastsetChainConfig(chain, env).apiUrl;
292
+
293
+ // src/sdk/Wallet.ts
294
+ var Wallet = class _Wallet {
295
+ constructor(privateKeyHex) {
296
+ const cleanPrivateKey = privateKeyHex.replace(/^0x/, "");
297
+ this.privateKey = Buffer.from(cleanPrivateKey, "hex");
298
+ this.publicKey = ed.getPublicKey(this.privateKey);
299
+ this.publicKeyHex = Buffer.from(this.publicKey).toString("hex");
300
+ }
301
+ toBech32() {
302
+ const words = bech325.bech32m.toWords(this.publicKey);
303
+ return bech325.bech32m.encode("set", words);
304
+ }
305
+ getWalletInfo() {
306
+ return {
307
+ publicKeyHex: this.publicKeyHex,
308
+ address: this.toBech32()
309
+ };
310
+ }
311
+ createTransferClaim(recipientAddress, amount, assetType) {
312
+ const recipientBytes = _Wallet.decodeBech32Address(recipientAddress);
313
+ const assetTypeBytes = new TextEncoder().encode(assetType);
314
+ const userData = new Uint8Array(32);
315
+ userData.set(assetTypeBytes.slice(0, 32));
316
+ return {
317
+ Transfer: {
318
+ recipient: { FastSet: recipientBytes },
319
+ amount: amount.toString(),
320
+ user_data: userData
321
+ }
322
+ };
323
+ }
324
+ createTransaction(nonce, recipient, claim) {
325
+ return new Transaction(this.publicKey, recipient, nonce, claim);
326
+ }
327
+ static decodeBech32Address(address) {
328
+ try {
329
+ const decoded = bech325.bech32m.decode(address);
330
+ return new Uint8Array(bech325.bech32m.fromWords(decoded.words));
331
+ } catch (error) {
332
+ const decoded = bech325.bech32.decode(address);
333
+ return new Uint8Array(bech325.bech32.fromWords(decoded.words));
334
+ }
335
+ }
336
+ static encodeBech32Address(publicKey) {
337
+ const words = bech325.bech32m.toWords(publicKey);
338
+ return bech325.bech32m.encode("set", words);
339
+ }
340
+ static fromPrivateKey(privateKeyHex) {
341
+ return new _Wallet(privateKeyHex);
342
+ }
343
+ static generateNew() {
344
+ const privateKey = ed.utils.randomPrivateKey();
345
+ const privateKeyHex = Buffer.from(privateKey).toString("hex");
346
+ return new _Wallet(privateKeyHex);
347
+ }
348
+ static async fromPrivateKeyFile(filePath) {
349
+ const fs = await import("fs/promises");
350
+ const privateKeyHex = (await fs.readFile(filePath, "utf8")).trim();
351
+ return new _Wallet(privateKeyHex);
352
+ }
225
353
  };
226
354
 
227
355
  // src/WarpFastsetSerializer.ts
@@ -243,7 +371,7 @@ var WarpFastsetSerializer = class {
243
371
  return `boolean:${value}`;
244
372
  }
245
373
  if (typeof value === "bigint") {
246
- return `bigint:${value.toString()}`;
374
+ return `biguint:${value.toString()}`;
247
375
  }
248
376
  if (Array.isArray(value)) {
249
377
  const items = value.map((item) => this.typedToString(item)).join(",");
@@ -268,7 +396,7 @@ var WarpFastsetSerializer = class {
268
396
  return ["boolean", value];
269
397
  }
270
398
  if (typeof value === "bigint") {
271
- return ["bigint", value];
399
+ return ["biguint", value.toString()];
272
400
  }
273
401
  return ["string", String(value)];
274
402
  }
@@ -280,8 +408,12 @@ var WarpFastsetSerializer = class {
280
408
  return Number(value);
281
409
  case "boolean":
282
410
  return Boolean(value);
283
- case "bigint":
411
+ case "biguint":
284
412
  return BigInt(value);
413
+ case "address":
414
+ return String(value);
415
+ case "hex":
416
+ return String(value);
285
417
  default:
286
418
  return String(value);
287
419
  }
@@ -294,8 +426,12 @@ var WarpFastsetSerializer = class {
294
426
  return "number";
295
427
  case "boolean":
296
428
  return "boolean";
297
- case "bigint":
298
- return "bigint";
429
+ case "biguint":
430
+ return "biguint";
431
+ case "address":
432
+ return "address";
433
+ case "hex":
434
+ return "hex";
299
435
  default:
300
436
  return "string";
301
437
  }
@@ -314,7 +450,7 @@ var WarpFastsetSerializer = class {
314
450
  return Number(stringValue);
315
451
  case "boolean":
316
452
  return stringValue === "true";
317
- case "bigint":
453
+ case "biguint":
318
454
  return BigInt(stringValue);
319
455
  case "array":
320
456
  return stringValue.split(",").map((item) => this.stringToTyped(item));
@@ -330,24 +466,29 @@ var WarpFastsetSerializer = class {
330
466
 
331
467
  // src/WarpFastsetExecutor.ts
332
468
  var WarpFastsetExecutor = class {
333
- constructor(config) {
469
+ constructor(config, chain) {
334
470
  this.config = config;
471
+ this.chain = chain;
335
472
  this.serializer = new WarpFastsetSerializer();
473
+ const proxyUrl = getProviderUrl(this.config, chain.name, this.config.env, this.chain.defaultApiUrl);
474
+ this.fastsetClient = new FastsetClient({
475
+ proxyUrl
476
+ });
336
477
  }
337
478
  async createTransaction(executable) {
338
479
  const action = getWarpActionByIndex(executable.warp, executable.action);
339
- let tx = null;
340
- if (action.type === "transfer") {
341
- tx = await this.createTransferTransaction(executable);
342
- } else if (action.type === "contract") {
343
- tx = await this.createContractCallTransaction(executable);
344
- } else if (action.type === "query") {
345
- throw new Error("WarpFastsetExecutor: Invalid action type for createTransaction; Use executeQuery instead");
346
- } else if (action.type === "collect") {
347
- throw new Error("WarpFastsetExecutor: Invalid action type for createTransaction; Use executeCollect instead");
348
- }
349
- if (!tx) throw new Error(`WarpFastsetExecutor: Invalid action type (${action.type})`);
350
- return tx;
480
+ switch (action.type) {
481
+ case "transfer":
482
+ return this.createTransferTransaction(executable);
483
+ case "contract":
484
+ return this.createContractCallTransaction(executable);
485
+ case "query":
486
+ throw new Error("WarpFastsetExecutor: Invalid action type for createTransaction; Use executeQuery instead");
487
+ case "collect":
488
+ throw new Error("WarpFastsetExecutor: Invalid action type for createTransaction; Use executeCollect instead");
489
+ default:
490
+ throw new Error(`WarpFastsetExecutor: Invalid action type (${action.type})`);
491
+ }
351
492
  }
352
493
  async createTransferTransaction(executable) {
353
494
  const userWallet = this.config.user?.wallets?.[executable.chain.name];
@@ -358,13 +499,15 @@ var WarpFastsetExecutor = class {
358
499
  if (executable.value < 0) {
359
500
  throw new Error(`WarpFastsetExecutor: Transfer value cannot be negative: ${executable.value}`);
360
501
  }
502
+ const recipientAddress = this.fromBase64(executable.destination);
503
+ const amount = this.normalizeAmount(executable.value.toString());
504
+ const userData = executable.data ? this.fromBase64(this.serializer.stringToTyped(executable.data)) : void 0;
361
505
  return {
362
506
  type: "fastset-transfer",
363
- from: userWallet,
364
- to: executable.destination,
365
- value: executable.value,
366
- data: executable.data ? this.serializer.stringToTyped(executable.data) : ""
367
- // TODO: Add Fastset-specific transaction fields
507
+ recipient: recipientAddress,
508
+ amount,
509
+ userData,
510
+ chain: executable.chain
368
511
  };
369
512
  }
370
513
  async createContractCallTransaction(executable) {
@@ -381,15 +524,15 @@ var WarpFastsetExecutor = class {
381
524
  throw new Error(`WarpFastsetExecutor: Contract call value cannot be negative: ${executable.value}`);
382
525
  }
383
526
  try {
527
+ const contractAddress = this.fromBase64(executable.destination);
384
528
  const encodedData = this.encodeFunctionData(action.func, executable.args);
385
529
  return {
386
530
  type: "fastset-contract-call",
387
- from: userWallet,
388
- to: executable.destination,
389
- value: executable.value,
531
+ contract: contractAddress,
532
+ function: action.func,
390
533
  data: encodedData,
391
- function: action.func
392
- // TODO: Add Fastset-specific transaction fields
534
+ value: executable.value,
535
+ chain: executable.chain
393
536
  };
394
537
  } catch (error) {
395
538
  throw new Error(`WarpFastsetExecutor: Failed to encode function data for ${action.func}: ${error}`);
@@ -407,46 +550,72 @@ var WarpFastsetExecutor = class {
407
550
  throw new Error(`WarpFastsetExecutor: Invalid contract address for query: ${executable.destination}`);
408
551
  }
409
552
  try {
410
- const result = await this.executeFastsetQuery(executable.destination, action.func, executable.args);
553
+ const contractAddress = this.fromBase64(executable.destination);
554
+ const result = await this.executeFastsetQuery(contractAddress, action.func, executable.args);
411
555
  return {
412
556
  success: true,
413
- result
414
- // TODO: Add Fastset-specific result fields
557
+ result,
558
+ chain: executable.chain
415
559
  };
416
560
  } catch (error) {
417
561
  return {
418
562
  success: false,
419
- error: error instanceof Error ? error.message : String(error)
420
- // TODO: Add Fastset-specific error fields
563
+ error: error instanceof Error ? error.message : String(error),
564
+ chain: executable.chain
421
565
  };
422
566
  }
423
567
  }
424
- async preprocessInput(chain, input, type, value) {
425
- const typedValue = this.serializer.stringToTyped(value);
426
- switch (type) {
427
- case "address":
428
- if (!this.isValidFastsetAddress(typedValue)) {
429
- throw new Error(`Invalid Fastset address format: ${typedValue}`);
430
- }
431
- return typedValue;
432
- case "number":
433
- const numValue = Number(typedValue);
434
- if (isNaN(numValue)) {
435
- throw new Error(`Invalid number format: ${typedValue}`);
436
- }
437
- return numValue.toString();
438
- case "bigint":
439
- const bigIntValue = BigInt(typedValue);
440
- if (bigIntValue < 0) {
441
- throw new Error(`Negative value not allowed for type ${type}: ${typedValue}`);
442
- }
443
- return bigIntValue.toString();
444
- default:
445
- return String(typedValue);
446
- }
568
+ async signMessage(message, privateKey) {
569
+ throw new Error("Not implemented");
447
570
  }
448
- isValidFastsetAddress(address) {
449
- return typeof address === "string" && address.length > 0;
571
+ async signTransaction(transaction, privateKey) {
572
+ const transactionJson = JSON.stringify(transaction, (key, value) => {
573
+ if (value instanceof Uint8Array) {
574
+ return Array.from(value);
575
+ }
576
+ return value;
577
+ });
578
+ const prefix = "Transaction::";
579
+ const dataToSign = new TextEncoder().encode(prefix + transactionJson);
580
+ return await ed25519.sign(dataToSign, privateKey);
581
+ }
582
+ async executeTransfer(executable) {
583
+ const userWallet = this.config.user?.wallets?.[executable.chain.name];
584
+ if (!userWallet) throw new Error("WarpFastsetExecutor: executeTransfer - user wallet not set");
585
+ const transaction = await this.createTransferTransaction(executable);
586
+ return {
587
+ success: true,
588
+ transaction,
589
+ chain: executable.chain.name,
590
+ message: "Transaction created successfully. Use executeTransferWithKey to execute with private key."
591
+ };
592
+ }
593
+ async executeTransferWithKey(executable, privateKey) {
594
+ const userWallet = this.config.user?.wallets?.[executable.chain.name];
595
+ if (!userWallet) throw new Error("WarpFastsetExecutor: executeTransfer - user wallet not set");
596
+ const transaction = await this.createTransferTransaction(executable);
597
+ const privateKeyBytes = this.fromBase64(privateKey);
598
+ const transactionData = {
599
+ sender: Array.from(privateKeyBytes.slice(0, 32)),
600
+ // First 32 bytes as public key
601
+ recipient: { FastSet: transaction.recipient },
602
+ nonce: await this.fastsetClient.getNextNonce(Wallet.encodeBech32Address(privateKeyBytes.slice(0, 32))),
603
+ timestamp_nanos: (BigInt(Date.now()) * 1000000n).toString(),
604
+ claim: {
605
+ Transfer: {
606
+ recipient: { FastSet: transaction.recipient },
607
+ amount: transaction.amount,
608
+ user_data: transaction.userData ? Array.from(transaction.userData) : null
609
+ }
610
+ }
611
+ };
612
+ const signature = await this.signTransaction(transactionData, privateKeyBytes);
613
+ const transactionHash = await this.fastsetClient.submitTransaction(transactionData, signature);
614
+ return {
615
+ success: true,
616
+ transactionHash: Array.from(transactionHash),
617
+ chain: executable.chain.name
618
+ };
450
619
  }
451
620
  encodeFunctionData(functionName, args) {
452
621
  return JSON.stringify({
@@ -455,13 +624,14 @@ var WarpFastsetExecutor = class {
455
624
  });
456
625
  }
457
626
  async executeFastsetQuery(contractAddress, functionName, args) {
458
- const response = await fetch(`${getFastsetApiUrl(this.config.env, "fastset")}/query`, {
627
+ const validatorUrl = getProviderUrl(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
628
+ const response = await fetch(`${validatorUrl}/query`, {
459
629
  method: "POST",
460
630
  headers: {
461
631
  "Content-Type": "application/json"
462
632
  },
463
633
  body: JSON.stringify({
464
- contract: contractAddress,
634
+ contract: Array.from(contractAddress),
465
635
  function: functionName,
466
636
  arguments: args
467
637
  })
@@ -471,39 +641,46 @@ var WarpFastsetExecutor = class {
471
641
  }
472
642
  return response.json();
473
643
  }
474
- async signMessage(message, privateKey) {
475
- throw new Error("Not implemented");
644
+ isValidFastsetAddress(address) {
645
+ if (typeof address !== "string" || address.length === 0) {
646
+ return false;
647
+ }
648
+ if (address.startsWith("fs") || address.startsWith("pi")) {
649
+ return true;
650
+ }
651
+ try {
652
+ const decoded = this.fromBase64(address);
653
+ return decoded.length === 32;
654
+ } catch {
655
+ return false;
656
+ }
657
+ }
658
+ fromBase64(base64) {
659
+ return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
660
+ }
661
+ normalizeAmount(amount) {
662
+ return amount.startsWith("0x") ? amount.slice(2) : amount;
476
663
  }
477
664
  };
478
665
 
479
666
  // src/WarpFastsetExplorer.ts
480
667
  var WarpFastsetExplorer = class {
481
- constructor(chainInfo, chainName = "fastset") {
482
- this.chainInfo = chainInfo;
483
- this.chainName = chainName;
668
+ constructor(_chainInfo, _config) {
669
+ this._chainInfo = _chainInfo;
670
+ this._config = _config;
671
+ this.explorerUrl = "https://explorer.fastset.xyz";
484
672
  }
485
673
  getAccountUrl(address) {
486
- const baseUrl = this.chainInfo.explorerUrl || this.getDefaultExplorerUrl();
487
- return `${baseUrl}/address/${address}`;
674
+ return `${this.explorerUrl}/account/${address}`;
488
675
  }
489
676
  getTransactionUrl(hash) {
490
- const baseUrl = this.chainInfo.explorerUrl || this.getDefaultExplorerUrl();
491
- return `${baseUrl}/tx/${hash}`;
677
+ return `${this.explorerUrl}/transaction/${hash}`;
492
678
  }
493
- getBlockUrl(blockNumber) {
494
- const baseUrl = this.chainInfo.explorerUrl || this.getDefaultExplorerUrl();
495
- return `${baseUrl}/block/${blockNumber}`;
679
+ getAssetUrl(identifier) {
680
+ return `${this.explorerUrl}/asset/${identifier}`;
496
681
  }
497
682
  getContractUrl(address) {
498
- const baseUrl = this.chainInfo.explorerUrl || this.getDefaultExplorerUrl();
499
- return `${baseUrl}/contract/${address}`;
500
- }
501
- getTokenUrl(address) {
502
- const baseUrl = this.chainInfo.explorerUrl || this.getDefaultExplorerUrl();
503
- return `${baseUrl}/token/${address}`;
504
- }
505
- getDefaultExplorerUrl() {
506
- return `https://explorer.fastset.xyz`;
683
+ return `${this.explorerUrl}/account/${address}`;
507
684
  }
508
685
  };
509
686
 
@@ -514,25 +691,26 @@ import {
514
691
  WarpConstants
515
692
  } from "@vleap/warps";
516
693
  var WarpFastsetResults = class {
517
- constructor(config) {
694
+ constructor(config, chain) {
518
695
  this.config = config;
696
+ this.chain = chain;
519
697
  this.serializer = new WarpFastsetSerializer();
520
698
  }
521
699
  async getTransactionExecutionResults(warp, tx) {
522
700
  const success = this.isTransactionSuccessful(tx);
523
- const gasUsed = this.extractGasUsed(tx);
524
- const gasPrice = this.extractGasPrice(tx);
525
- const blockNumber = this.extractBlockNumber(tx);
526
701
  const transactionHash = this.extractTransactionHash(tx);
527
- const logs = this.extractLogs(tx);
702
+ const blockNumber = this.extractBlockNumber(tx);
703
+ const timestamp = this.extractTimestamp(tx);
528
704
  return {
529
705
  success,
530
706
  warp,
531
707
  action: 0,
532
- user: this.config.user?.wallets?.fastset || null,
708
+ user: this.config.user?.wallets?.[this.chain.name] || null,
533
709
  txHash: transactionHash,
710
+ tx,
534
711
  next: null,
535
- values: [transactionHash, blockNumber, gasUsed, gasPrice, ...logs.length > 0 ? logs : []],
712
+ values: [transactionHash, blockNumber, timestamp],
713
+ valuesRaw: [transactionHash, blockNumber, timestamp],
536
714
  results: {},
537
715
  messages: {}
538
716
  };
@@ -543,6 +721,11 @@ var WarpFastsetResults = class {
543
721
  let results = {};
544
722
  if (!warp.results) return { values, results };
545
723
  const getNestedValue = (path) => {
724
+ const match = path.match(/^out\[(\d+)\]$/);
725
+ if (match) {
726
+ const index = parseInt(match[1]) - 1;
727
+ return valuesRaw[index];
728
+ }
546
729
  const indices = path.split(".").slice(1).map((i) => parseInt(i) - 1);
547
730
  if (indices.length === 0) return void 0;
548
731
  let value = valuesRaw[indices[0]];
@@ -560,60 +743,101 @@ var WarpFastsetResults = class {
560
743
  continue;
561
744
  }
562
745
  if (path.startsWith("out.") || path === "out" || path.startsWith("out[")) {
563
- results[key] = getNestedValue(path) || null;
746
+ const value = getNestedValue(path);
747
+ results[key] = value || null;
564
748
  } else {
565
749
  results[key] = path;
566
750
  }
567
751
  }
568
- return { values, results: await evaluateResultsCommon(warp, results, actionIndex, inputs) };
752
+ return { values, results: await evaluateResultsCommon(warp, results, actionIndex, inputs, this.config.transform?.runner) };
569
753
  }
570
754
  isTransactionSuccessful(tx) {
571
- return tx.status === "success" || tx.status === 1 || tx.success === true;
572
- }
573
- extractGasUsed(tx) {
574
- return tx.gasUsed?.toString() || tx.gas_used?.toString() || "0";
755
+ if (!tx) return false;
756
+ if (tx.success === false) return false;
757
+ if (tx.success === true) return true;
758
+ if (tx.status === "success") return true;
759
+ if (tx.status === 1) return true;
760
+ if (tx.result && tx.result.success === true) return true;
761
+ return false;
575
762
  }
576
- extractGasPrice(tx) {
577
- return tx.gasPrice?.toString() || tx.gas_price?.toString() || "0";
763
+ extractTransactionHash(tx) {
764
+ if (!tx) return "";
765
+ return tx.transaction_hash || tx.transactionHash || tx.hash || tx.result && tx.result.transaction_hash || "";
578
766
  }
579
767
  extractBlockNumber(tx) {
580
- return tx.blockNumber?.toString() || tx.block_number?.toString() || "0";
768
+ if (!tx) return "0";
769
+ return tx.block_number?.toString() || tx.blockNumber?.toString() || tx.result && tx.result.block_number?.toString() || "0";
581
770
  }
582
- extractTransactionHash(tx) {
583
- return tx.hash || tx.transactionHash || tx.transaction_hash || "";
584
- }
585
- extractLogs(tx) {
586
- const logs = tx.logs || tx.events || [];
587
- return logs.map((log) => ({
588
- address: log.address || log.contract,
589
- topics: log.topics || log.topics || [],
590
- data: log.data || log.payload || "",
591
- blockNumber: log.blockNumber?.toString() || log.block_number?.toString() || "0",
592
- transactionHash: log.transactionHash || log.transaction_hash || "",
593
- index: log.index?.toString() || "0"
594
- }));
771
+ extractTimestamp(tx) {
772
+ if (!tx) return "0";
773
+ return tx.timestamp?.toString() || tx.timestamp_nanos?.toString() || tx.result && tx.result.timestamp?.toString() || Date.now().toString();
595
774
  }
596
775
  };
597
776
 
598
777
  // src/main.ts
599
- var getFastsetAdapter = (config, fallback) => {
600
- if (!fallback) throw new Error("Fastset adapter requires a fallback adapter");
601
- return {
602
- chain: WarpFastsetConstants.ChainName,
603
- prefix: WarpFastsetConstants.ChainPrefix,
604
- builder: () => new WarpFastsetBuilder(config),
605
- executor: new WarpFastsetExecutor(config),
606
- results: new WarpFastsetResults(config),
607
- serializer: new WarpFastsetSerializer(),
608
- registry: fallback.registry,
609
- explorer: (chainInfo) => new WarpFastsetExplorer(chainInfo),
610
- abiBuilder: () => fallback.abiBuilder(),
611
- brandBuilder: () => fallback.brandBuilder()
612
- };
778
+ var NativeTokenSet = {
779
+ chain: WarpChainName.Fastset,
780
+ identifier: "SET",
781
+ name: "SET",
782
+ symbol: "SET",
783
+ decimals: 6,
784
+ logoUrl: "https://vleap.ai/images/tokens/set.svg"
613
785
  };
786
+ function createFastsetAdapter(chainName, chainPrefix, chainInfos) {
787
+ return (config, fallback) => {
788
+ const chainInfo = chainInfos[config.env];
789
+ if (!chainInfo) throw new Error(`FastsetAdapter: chain info not found for chain ${chainName}`);
790
+ if (!fallback) throw new Error("Fastset adapter requires a fallback adapter");
791
+ return {
792
+ chain: chainName,
793
+ chainInfo,
794
+ prefix: chainPrefix,
795
+ builder: () => fallback.builder(),
796
+ executor: new WarpFastsetExecutor(config, chainInfo),
797
+ results: new WarpFastsetResults(config, chainInfo),
798
+ serializer: new WarpFastsetSerializer(),
799
+ registry: fallback.registry,
800
+ explorer: new WarpFastsetExplorer(chainInfo, config),
801
+ abiBuilder: () => fallback.abiBuilder(),
802
+ brandBuilder: () => fallback.brandBuilder(),
803
+ dataLoader: new WarpFastsetDataLoader(config, chainInfo)
804
+ };
805
+ };
806
+ }
807
+ var getFastsetAdapter = createFastsetAdapter(WarpChainName.Fastset, "fastset", {
808
+ mainnet: {
809
+ name: WarpChainName.Fastset,
810
+ displayName: "FastSet",
811
+ chainId: "1",
812
+ blockTime: 1e3,
813
+ addressHrp: "set",
814
+ defaultApiUrl: "https://rpc.fastset.xyz",
815
+ nativeToken: NativeTokenSet
816
+ },
817
+ testnet: {
818
+ name: WarpChainName.Fastset,
819
+ displayName: "FastSet Testnet",
820
+ chainId: "testnet",
821
+ blockTime: 1e3,
822
+ addressHrp: "set",
823
+ defaultApiUrl: "https://rpc.fastset.xyz",
824
+ nativeToken: NativeTokenSet
825
+ },
826
+ devnet: {
827
+ name: WarpChainName.Fastset,
828
+ displayName: "FastSet Devnet",
829
+ chainId: "devnet",
830
+ blockTime: 1e3,
831
+ addressHrp: "set",
832
+ defaultApiUrl: "https://rpc.fastset.xyz",
833
+ nativeToken: NativeTokenSet
834
+ }
835
+ });
614
836
  export {
615
- WarpFastsetBuilder,
837
+ FastsetClient,
838
+ NativeTokenSet,
616
839
  WarpFastsetConstants,
840
+ WarpFastsetDataLoader,
617
841
  WarpFastsetExecutor,
618
842
  WarpFastsetExplorer,
619
843
  WarpFastsetResults,