moltspay 1.5.0 → 1.6.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 +142 -0
- package/dist/cli/index.js +476 -144
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +473 -141
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +5 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js +235 -108
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +231 -106
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/web/index.d.mts +418 -0
- package/dist/client/web/index.mjs +1289 -0
- package/dist/client/web/index.mjs.map +1 -0
- package/dist/facilitators/index.d.mts +24 -2
- package/dist/facilitators/index.d.ts +24 -2
- package/dist/facilitators/index.js +127 -13
- package/dist/facilitators/index.js.map +1 -1
- package/dist/facilitators/index.mjs +127 -13
- package/dist/facilitators/index.mjs.map +1 -1
- package/dist/index.js +453 -141
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +450 -138
- package/dist/index.mjs.map +1 -1
- package/dist/mcp/index.js +234 -109
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/index.mjs +231 -106
- package/dist/mcp/index.mjs.map +1 -1
- package/dist/server/index.d.mts +43 -1
- package/dist/server/index.d.ts +43 -1
- package/dist/server/index.js +205 -18
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +205 -18
- package/dist/server/index.mjs.map +1 -1
- package/package.json +9 -2
package/dist/client/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// src/client/index.ts
|
|
1
|
+
// src/client/node/index.ts
|
|
2
2
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, statSync, chmodSync } from "fs";
|
|
3
3
|
import { homedir as homedir2 } from "os";
|
|
4
4
|
import { join as join2 } from "path";
|
|
5
|
-
import { Wallet, ethers } from "ethers";
|
|
5
|
+
import { Wallet as Wallet2, ethers as ethers2 } from "ethers";
|
|
6
6
|
|
|
7
7
|
// src/chains/index.ts
|
|
8
8
|
var CHAINS = {
|
|
@@ -253,16 +253,16 @@ import {
|
|
|
253
253
|
getAccount as getAccount2,
|
|
254
254
|
createAssociatedTokenAccountInstruction
|
|
255
255
|
} from "@solana/spl-token";
|
|
256
|
-
async function createSolanaPaymentTransaction(senderPubkey, recipientPubkey, amount, chain, feePayerPubkey) {
|
|
256
|
+
async function createSolanaPaymentTransaction(senderPubkey, recipientPubkey, amount, chain, feePayerPubkey, connection) {
|
|
257
257
|
const chainConfig = SOLANA_CHAINS[chain];
|
|
258
|
-
const
|
|
258
|
+
const conn = connection ?? new Connection3(chainConfig.rpc, "confirmed");
|
|
259
259
|
const mint = new PublicKey3(chainConfig.tokens.USDC.mint);
|
|
260
260
|
const actualFeePayer = feePayerPubkey || senderPubkey;
|
|
261
261
|
const senderATA = await getAssociatedTokenAddress2(mint, senderPubkey);
|
|
262
262
|
const recipientATA = await getAssociatedTokenAddress2(mint, recipientPubkey);
|
|
263
263
|
const transaction = new Transaction();
|
|
264
264
|
try {
|
|
265
|
-
await getAccount2(
|
|
265
|
+
await getAccount2(conn, recipientATA);
|
|
266
266
|
} catch {
|
|
267
267
|
transaction.add(
|
|
268
268
|
createAssociatedTokenAccountInstruction(
|
|
@@ -293,17 +293,178 @@ async function createSolanaPaymentTransaction(senderPubkey, recipientPubkey, amo
|
|
|
293
293
|
// decimals
|
|
294
294
|
)
|
|
295
295
|
);
|
|
296
|
-
const { blockhash, lastValidBlockHeight } = await
|
|
296
|
+
const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash();
|
|
297
297
|
transaction.recentBlockhash = blockhash;
|
|
298
298
|
transaction.feePayer = actualFeePayer;
|
|
299
299
|
return transaction;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
-
// src/client/index.ts
|
|
302
|
+
// src/client/node/index.ts
|
|
303
303
|
import { PublicKey as PublicKey4 } from "@solana/web3.js";
|
|
304
|
+
|
|
305
|
+
// src/client/core/types.ts
|
|
304
306
|
var X402_VERSION = 2;
|
|
305
307
|
var PAYMENT_REQUIRED_HEADER = "x-payment-required";
|
|
306
308
|
var PAYMENT_HEADER = "x-payment";
|
|
309
|
+
|
|
310
|
+
// src/client/core/chain-map.ts
|
|
311
|
+
var NETWORK_TO_CHAIN = {
|
|
312
|
+
"eip155:8453": "base",
|
|
313
|
+
"eip155:137": "polygon",
|
|
314
|
+
"eip155:84532": "base_sepolia",
|
|
315
|
+
"eip155:42431": "tempo_moderato",
|
|
316
|
+
"eip155:56": "bnb",
|
|
317
|
+
"eip155:97": "bnb_testnet",
|
|
318
|
+
"solana:mainnet": "solana",
|
|
319
|
+
"solana:devnet": "solana_devnet"
|
|
320
|
+
};
|
|
321
|
+
var CHAIN_TO_NETWORK = Object.fromEntries(
|
|
322
|
+
Object.entries(NETWORK_TO_CHAIN).map(([network, chain]) => [chain, network])
|
|
323
|
+
);
|
|
324
|
+
function networkToChainName(network) {
|
|
325
|
+
return NETWORK_TO_CHAIN[network] ?? null;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// src/client/core/base64.ts
|
|
329
|
+
var BufferCtor = globalThis.Buffer;
|
|
330
|
+
|
|
331
|
+
// src/client/core/eip3009.ts
|
|
332
|
+
var EIP3009_TYPES = {
|
|
333
|
+
TransferWithAuthorization: [
|
|
334
|
+
{ name: "from", type: "address" },
|
|
335
|
+
{ name: "to", type: "address" },
|
|
336
|
+
{ name: "value", type: "uint256" },
|
|
337
|
+
{ name: "validAfter", type: "uint256" },
|
|
338
|
+
{ name: "validBefore", type: "uint256" },
|
|
339
|
+
{ name: "nonce", type: "bytes32" }
|
|
340
|
+
]
|
|
341
|
+
};
|
|
342
|
+
function buildEIP3009TypedData(args) {
|
|
343
|
+
const validAfter = args.validAfter ?? "0";
|
|
344
|
+
const validBefore = args.validBefore ?? (Math.floor(Date.now() / 1e3) + 3600).toString();
|
|
345
|
+
const authorization = {
|
|
346
|
+
from: args.from,
|
|
347
|
+
to: args.to,
|
|
348
|
+
value: args.value,
|
|
349
|
+
validAfter,
|
|
350
|
+
validBefore,
|
|
351
|
+
nonce: args.nonce
|
|
352
|
+
};
|
|
353
|
+
return {
|
|
354
|
+
domain: {
|
|
355
|
+
name: args.tokenName,
|
|
356
|
+
version: args.tokenVersion,
|
|
357
|
+
chainId: args.chainId,
|
|
358
|
+
verifyingContract: args.tokenAddress
|
|
359
|
+
},
|
|
360
|
+
types: EIP3009_TYPES,
|
|
361
|
+
primaryType: "TransferWithAuthorization",
|
|
362
|
+
message: authorization
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/client/core/bnb-intent.ts
|
|
367
|
+
var BNB_INTENT_TYPES = {
|
|
368
|
+
PaymentIntent: [
|
|
369
|
+
{ name: "from", type: "address" },
|
|
370
|
+
{ name: "to", type: "address" },
|
|
371
|
+
{ name: "amount", type: "uint256" },
|
|
372
|
+
{ name: "token", type: "address" },
|
|
373
|
+
{ name: "service", type: "string" },
|
|
374
|
+
{ name: "nonce", type: "uint256" },
|
|
375
|
+
{ name: "deadline", type: "uint256" }
|
|
376
|
+
]
|
|
377
|
+
};
|
|
378
|
+
var BNB_DOMAIN_NAME = "MoltsPay";
|
|
379
|
+
var BNB_DOMAIN_VERSION = "1";
|
|
380
|
+
function buildBnbIntentTypedData(args) {
|
|
381
|
+
const intent = {
|
|
382
|
+
from: args.from,
|
|
383
|
+
to: args.to,
|
|
384
|
+
amount: args.amount,
|
|
385
|
+
token: args.tokenAddress,
|
|
386
|
+
service: args.service,
|
|
387
|
+
nonce: args.nonce,
|
|
388
|
+
deadline: args.deadline
|
|
389
|
+
};
|
|
390
|
+
return {
|
|
391
|
+
domain: {
|
|
392
|
+
name: BNB_DOMAIN_NAME,
|
|
393
|
+
version: BNB_DOMAIN_VERSION,
|
|
394
|
+
chainId: args.chainId
|
|
395
|
+
},
|
|
396
|
+
types: BNB_INTENT_TYPES,
|
|
397
|
+
primaryType: "PaymentIntent",
|
|
398
|
+
message: intent
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/client/node/signer.ts
|
|
403
|
+
import { ethers } from "ethers";
|
|
404
|
+
import { Transaction as Transaction2 } from "@solana/web3.js";
|
|
405
|
+
var NodeSigner = class {
|
|
406
|
+
evmWallet;
|
|
407
|
+
getSolanaKeypair;
|
|
408
|
+
constructor(evmWallet, options = {}) {
|
|
409
|
+
this.evmWallet = evmWallet;
|
|
410
|
+
this.getSolanaKeypair = options.getSolanaKeypair ?? (() => null);
|
|
411
|
+
}
|
|
412
|
+
async getEvmAddress() {
|
|
413
|
+
return this.evmWallet.address;
|
|
414
|
+
}
|
|
415
|
+
async getSolanaAddress() {
|
|
416
|
+
const kp = this.getSolanaKeypair();
|
|
417
|
+
return kp ? kp.publicKey.toBase58() : null;
|
|
418
|
+
}
|
|
419
|
+
async signTypedData(envelope) {
|
|
420
|
+
const mutableTypes = {};
|
|
421
|
+
for (const [key, fields] of Object.entries(envelope.types)) {
|
|
422
|
+
mutableTypes[key] = [...fields];
|
|
423
|
+
}
|
|
424
|
+
return this.evmWallet.signTypedData(
|
|
425
|
+
envelope.domain,
|
|
426
|
+
mutableTypes,
|
|
427
|
+
envelope.message
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
async sendEvmTransaction(args) {
|
|
431
|
+
const chain = findChainByChainId(args.chainId);
|
|
432
|
+
if (!chain) {
|
|
433
|
+
throw new Error(`sendEvmTransaction: unknown chainId ${args.chainId}`);
|
|
434
|
+
}
|
|
435
|
+
const provider = new ethers.JsonRpcProvider(chain.rpc);
|
|
436
|
+
const connected = this.evmWallet.connect(provider);
|
|
437
|
+
const tx = await connected.sendTransaction({
|
|
438
|
+
to: args.to,
|
|
439
|
+
data: args.data,
|
|
440
|
+
value: args.value ? BigInt(args.value) : 0n
|
|
441
|
+
});
|
|
442
|
+
return tx.hash;
|
|
443
|
+
}
|
|
444
|
+
async signSolanaTransaction(args) {
|
|
445
|
+
const kp = this.getSolanaKeypair();
|
|
446
|
+
if (!kp) {
|
|
447
|
+
throw new Error("signSolanaTransaction: no Solana wallet configured");
|
|
448
|
+
}
|
|
449
|
+
const tx = Transaction2.from(Buffer.from(args.transactionBase64, "base64"));
|
|
450
|
+
if (args.partialSign) {
|
|
451
|
+
tx.partialSign(kp);
|
|
452
|
+
} else {
|
|
453
|
+
tx.sign(kp);
|
|
454
|
+
}
|
|
455
|
+
return tx.serialize({ requireAllSignatures: false }).toString("base64");
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
function findChainByChainId(chainId) {
|
|
459
|
+
for (const cfg of Object.values(CHAINS)) {
|
|
460
|
+
if (cfg.chainId === chainId) {
|
|
461
|
+
return cfg;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return void 0;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// src/client/node/index.ts
|
|
307
468
|
var DEFAULT_CONFIG = {
|
|
308
469
|
chain: "base",
|
|
309
470
|
limits: {
|
|
@@ -316,6 +477,7 @@ var MoltsPayClient = class {
|
|
|
316
477
|
config;
|
|
317
478
|
walletData = null;
|
|
318
479
|
wallet = null;
|
|
480
|
+
signer = null;
|
|
319
481
|
todaySpending = 0;
|
|
320
482
|
lastSpendingReset = 0;
|
|
321
483
|
constructor(options = {}) {
|
|
@@ -324,7 +486,11 @@ var MoltsPayClient = class {
|
|
|
324
486
|
this.walletData = this.loadWallet();
|
|
325
487
|
this.loadSpending();
|
|
326
488
|
if (this.walletData) {
|
|
327
|
-
this.wallet = new
|
|
489
|
+
this.wallet = new Wallet2(this.walletData.privateKey);
|
|
490
|
+
const configDir = this.configDir;
|
|
491
|
+
this.signer = new NodeSigner(this.wallet, {
|
|
492
|
+
getSolanaKeypair: () => loadSolanaWallet(configDir)
|
|
493
|
+
});
|
|
328
494
|
}
|
|
329
495
|
}
|
|
330
496
|
/**
|
|
@@ -452,20 +618,6 @@ var MoltsPayClient = class {
|
|
|
452
618
|
} catch {
|
|
453
619
|
throw new Error("Invalid x-payment-required header");
|
|
454
620
|
}
|
|
455
|
-
const networkToChainName = (network2) => {
|
|
456
|
-
if (network2 === "solana:mainnet") return "solana";
|
|
457
|
-
if (network2 === "solana:devnet") return "solana_devnet";
|
|
458
|
-
const match = network2.match(/^eip155:(\d+)$/);
|
|
459
|
-
if (!match) return null;
|
|
460
|
-
const chainId = parseInt(match[1]);
|
|
461
|
-
if (chainId === 8453) return "base";
|
|
462
|
-
if (chainId === 137) return "polygon";
|
|
463
|
-
if (chainId === 84532) return "base_sepolia";
|
|
464
|
-
if (chainId === 42431) return "tempo_moderato";
|
|
465
|
-
if (chainId === 56) return "bnb";
|
|
466
|
-
if (chainId === 97) return "bnb_testnet";
|
|
467
|
-
return null;
|
|
468
|
-
};
|
|
469
621
|
const serverChains = requirements.map((r) => networkToChainName(r.network)).filter((c) => c !== null);
|
|
470
622
|
const userSpecifiedChain = options.chain;
|
|
471
623
|
let selectedChain;
|
|
@@ -694,14 +846,14 @@ Please specify: --chain <chain_name>`
|
|
|
694
846
|
async handleBNBPayment(executeUrl, service, params, paymentDetails, options = {}) {
|
|
695
847
|
const { to, amount, token, chainName, chain, spender } = paymentDetails;
|
|
696
848
|
const tokenConfig = chain.tokens[token];
|
|
697
|
-
const provider = new
|
|
849
|
+
const provider = new ethers2.JsonRpcProvider(chain.rpc);
|
|
698
850
|
const allowance = await this.checkAllowance(tokenConfig.address, spender, provider);
|
|
699
851
|
const amountWeiCheck = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals));
|
|
700
852
|
if (allowance < amountWeiCheck) {
|
|
701
853
|
const nativeBalance = await provider.getBalance(this.wallet.address);
|
|
702
|
-
const minGasBalance =
|
|
854
|
+
const minGasBalance = ethers2.parseEther("0.0005");
|
|
703
855
|
if (nativeBalance < minGasBalance) {
|
|
704
|
-
const nativeBNB = parseFloat(
|
|
856
|
+
const nativeBNB = parseFloat(ethers2.formatEther(nativeBalance)).toFixed(4);
|
|
705
857
|
const isTestnet = chainName === "bnb_testnet";
|
|
706
858
|
if (isTestnet) {
|
|
707
859
|
throw new Error(
|
|
@@ -735,35 +887,21 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
735
887
|
);
|
|
736
888
|
}
|
|
737
889
|
const amountWei = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals)).toString();
|
|
738
|
-
const
|
|
890
|
+
const intentNonce = Date.now();
|
|
891
|
+
const intentDeadline = Date.now() + 36e5;
|
|
892
|
+
const envelope = buildBnbIntentTypedData({
|
|
739
893
|
from: this.wallet.address,
|
|
740
894
|
to,
|
|
741
895
|
amount: amountWei,
|
|
742
|
-
|
|
896
|
+
tokenAddress: tokenConfig.address,
|
|
743
897
|
service,
|
|
744
|
-
nonce:
|
|
745
|
-
|
|
746
|
-
deadline: Date.now() + 36e5
|
|
747
|
-
// 1 hour
|
|
748
|
-
};
|
|
749
|
-
const domain = {
|
|
750
|
-
name: "MoltsPay",
|
|
751
|
-
version: "1",
|
|
898
|
+
nonce: intentNonce,
|
|
899
|
+
deadline: intentDeadline,
|
|
752
900
|
chainId: chain.chainId
|
|
753
|
-
};
|
|
754
|
-
const types = {
|
|
755
|
-
PaymentIntent: [
|
|
756
|
-
{ name: "from", type: "address" },
|
|
757
|
-
{ name: "to", type: "address" },
|
|
758
|
-
{ name: "amount", type: "uint256" },
|
|
759
|
-
{ name: "token", type: "address" },
|
|
760
|
-
{ name: "service", type: "string" },
|
|
761
|
-
{ name: "nonce", type: "uint256" },
|
|
762
|
-
{ name: "deadline", type: "uint256" }
|
|
763
|
-
]
|
|
764
|
-
};
|
|
901
|
+
});
|
|
765
902
|
console.log(`[MoltsPay] Signing BNB payment intent...`);
|
|
766
|
-
const signature = await this.
|
|
903
|
+
const signature = await this.signer.signTypedData(envelope);
|
|
904
|
+
const intent = envelope.message;
|
|
767
905
|
const network = `eip155:${chain.chainId}`;
|
|
768
906
|
const payload = {
|
|
769
907
|
x402Version: 2,
|
|
@@ -837,12 +975,11 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
837
975
|
feePayerPubkey
|
|
838
976
|
// Optional fee payer for gasless mode
|
|
839
977
|
);
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
const signedTx = transaction.serialize({ requireAllSignatures: false }).toString("base64");
|
|
978
|
+
const unsignedBase64 = transaction.serialize({ requireAllSignatures: false, verifySignatures: false }).toString("base64");
|
|
979
|
+
const signedTx = await this.signer.signSolanaTransaction({
|
|
980
|
+
transactionBase64: unsignedBase64,
|
|
981
|
+
partialSign: !!feePayerPubkey
|
|
982
|
+
});
|
|
846
983
|
console.log(`[MoltsPay] Transaction signed, sending to server...`);
|
|
847
984
|
const network = chain === "solana" ? "solana:mainnet" : "solana:devnet";
|
|
848
985
|
const payload = {
|
|
@@ -889,7 +1026,7 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
889
1026
|
* Check ERC20 allowance for a spender
|
|
890
1027
|
*/
|
|
891
1028
|
async checkAllowance(tokenAddress, spender, provider) {
|
|
892
|
-
const contract = new
|
|
1029
|
+
const contract = new ethers2.Contract(
|
|
893
1030
|
tokenAddress,
|
|
894
1031
|
["function allowance(address owner, address spender) view returns (uint256)"],
|
|
895
1032
|
provider
|
|
@@ -900,41 +1037,29 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
900
1037
|
* Sign EIP-3009 transferWithAuthorization (GASLESS)
|
|
901
1038
|
* This only signs - no on-chain transaction, no gas needed.
|
|
902
1039
|
* Supports both USDC and USDT.
|
|
1040
|
+
*
|
|
1041
|
+
* Delegates typed-data construction to `core/eip3009.ts` and the signature
|
|
1042
|
+
* itself to `this.signer`. That way Web Client (Phase 4) can reuse the same
|
|
1043
|
+
* flow with an EIP-1193 signer without duplicating typed-data layout.
|
|
903
1044
|
*/
|
|
904
1045
|
async signEIP3009(to, amount, chain, token = "USDC", domainOverride) {
|
|
905
|
-
const validAfter = 0;
|
|
906
|
-
const validBefore = Math.floor(Date.now() / 1e3) + 3600;
|
|
907
|
-
const nonce = ethers.hexlify(ethers.randomBytes(32));
|
|
908
1046
|
const tokenConfig = chain.tokens[token];
|
|
909
1047
|
const value = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals)).toString();
|
|
910
|
-
const
|
|
1048
|
+
const nonce = ethers2.hexlify(ethers2.randomBytes(32));
|
|
1049
|
+
const tokenName = domainOverride?.name || tokenConfig.eip712Name || (token === "USDC" ? "USD Coin" : "Tether USD");
|
|
1050
|
+
const tokenVersion = domainOverride?.version || "2";
|
|
1051
|
+
const envelope = buildEIP3009TypedData({
|
|
911
1052
|
from: this.wallet.address,
|
|
912
1053
|
to,
|
|
913
1054
|
value,
|
|
914
|
-
|
|
915
|
-
validBefore: validBefore.toString(),
|
|
916
|
-
nonce
|
|
917
|
-
};
|
|
918
|
-
const tokenName = domainOverride?.name || tokenConfig.eip712Name || (token === "USDC" ? "USD Coin" : "Tether USD");
|
|
919
|
-
const tokenVersion = domainOverride?.version || "2";
|
|
920
|
-
const domain = {
|
|
921
|
-
name: tokenName,
|
|
922
|
-
version: tokenVersion,
|
|
1055
|
+
nonce,
|
|
923
1056
|
chainId: chain.chainId,
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
{ name: "value", type: "uint256" },
|
|
931
|
-
{ name: "validAfter", type: "uint256" },
|
|
932
|
-
{ name: "validBefore", type: "uint256" },
|
|
933
|
-
{ name: "nonce", type: "bytes32" }
|
|
934
|
-
]
|
|
935
|
-
};
|
|
936
|
-
const signature = await this.wallet.signTypedData(domain, types, authorization);
|
|
937
|
-
return { authorization, signature };
|
|
1057
|
+
tokenAddress: tokenConfig.address,
|
|
1058
|
+
tokenName,
|
|
1059
|
+
tokenVersion
|
|
1060
|
+
});
|
|
1061
|
+
const signature = await this.signer.signTypedData(envelope);
|
|
1062
|
+
return { authorization: envelope.message, signature };
|
|
938
1063
|
}
|
|
939
1064
|
/**
|
|
940
1065
|
* Check spending limits
|
|
@@ -1038,7 +1163,7 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
1038
1163
|
*/
|
|
1039
1164
|
static init(configDir, options) {
|
|
1040
1165
|
mkdirSync2(configDir, { recursive: true });
|
|
1041
|
-
const wallet =
|
|
1166
|
+
const wallet = Wallet2.createRandom();
|
|
1042
1167
|
const walletData = {
|
|
1043
1168
|
address: wallet.address,
|
|
1044
1169
|
privateKey: wallet.privateKey,
|
|
@@ -1070,17 +1195,17 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
1070
1195
|
} catch {
|
|
1071
1196
|
throw new Error(`Unknown chain: ${this.config.chain}`);
|
|
1072
1197
|
}
|
|
1073
|
-
const provider = new
|
|
1198
|
+
const provider = new ethers2.JsonRpcProvider(chain.rpc);
|
|
1074
1199
|
const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
|
|
1075
1200
|
const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
|
|
1076
1201
|
provider.getBalance(this.wallet.address),
|
|
1077
|
-
new
|
|
1078
|
-
new
|
|
1202
|
+
new ethers2.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
1203
|
+
new ethers2.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
|
|
1079
1204
|
]);
|
|
1080
1205
|
return {
|
|
1081
|
-
usdc: parseFloat(
|
|
1082
|
-
usdt: parseFloat(
|
|
1083
|
-
native: parseFloat(
|
|
1206
|
+
usdc: parseFloat(ethers2.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),
|
|
1207
|
+
usdt: parseFloat(ethers2.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),
|
|
1208
|
+
native: parseFloat(ethers2.formatEther(nativeBalance))
|
|
1084
1209
|
};
|
|
1085
1210
|
}
|
|
1086
1211
|
/**
|
|
@@ -1103,38 +1228,38 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
1103
1228
|
supportedChains.map(async (chainName) => {
|
|
1104
1229
|
try {
|
|
1105
1230
|
const chain = getChain(chainName);
|
|
1106
|
-
const provider = new
|
|
1231
|
+
const provider = new ethers2.JsonRpcProvider(chain.rpc);
|
|
1107
1232
|
if (chainName === "tempo_moderato") {
|
|
1108
1233
|
const [nativeBalance, pathUSD, alphaUSD, betaUSD, thetaUSD] = await Promise.all([
|
|
1109
1234
|
provider.getBalance(this.wallet.address),
|
|
1110
|
-
new
|
|
1111
|
-
new
|
|
1112
|
-
new
|
|
1113
|
-
new
|
|
1235
|
+
new ethers2.Contract(tempoTokens.pathUSD, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
1236
|
+
new ethers2.Contract(tempoTokens.alphaUSD, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
1237
|
+
new ethers2.Contract(tempoTokens.betaUSD, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
1238
|
+
new ethers2.Contract(tempoTokens.thetaUSD, tokenAbi, provider).balanceOf(this.wallet.address)
|
|
1114
1239
|
]);
|
|
1115
1240
|
results[chainName] = {
|
|
1116
|
-
usdc: parseFloat(
|
|
1241
|
+
usdc: parseFloat(ethers2.formatUnits(pathUSD, 6)),
|
|
1117
1242
|
// pathUSD as default USDC
|
|
1118
|
-
usdt: parseFloat(
|
|
1243
|
+
usdt: parseFloat(ethers2.formatUnits(alphaUSD, 6)),
|
|
1119
1244
|
// alphaUSD as default USDT
|
|
1120
|
-
native: parseFloat(
|
|
1245
|
+
native: parseFloat(ethers2.formatEther(nativeBalance)),
|
|
1121
1246
|
tempo: {
|
|
1122
|
-
pathUSD: parseFloat(
|
|
1123
|
-
alphaUSD: parseFloat(
|
|
1124
|
-
betaUSD: parseFloat(
|
|
1125
|
-
thetaUSD: parseFloat(
|
|
1247
|
+
pathUSD: parseFloat(ethers2.formatUnits(pathUSD, 6)),
|
|
1248
|
+
alphaUSD: parseFloat(ethers2.formatUnits(alphaUSD, 6)),
|
|
1249
|
+
betaUSD: parseFloat(ethers2.formatUnits(betaUSD, 6)),
|
|
1250
|
+
thetaUSD: parseFloat(ethers2.formatUnits(thetaUSD, 6))
|
|
1126
1251
|
}
|
|
1127
1252
|
};
|
|
1128
1253
|
} else {
|
|
1129
1254
|
const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
|
|
1130
1255
|
provider.getBalance(this.wallet.address),
|
|
1131
|
-
new
|
|
1132
|
-
new
|
|
1256
|
+
new ethers2.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
1257
|
+
new ethers2.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
|
|
1133
1258
|
]);
|
|
1134
1259
|
results[chainName] = {
|
|
1135
|
-
usdc: parseFloat(
|
|
1136
|
-
usdt: parseFloat(
|
|
1137
|
-
native: parseFloat(
|
|
1260
|
+
usdc: parseFloat(ethers2.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),
|
|
1261
|
+
usdt: parseFloat(ethers2.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),
|
|
1262
|
+
native: parseFloat(ethers2.formatEther(nativeBalance))
|
|
1138
1263
|
};
|
|
1139
1264
|
}
|
|
1140
1265
|
} catch (err) {
|