moltspay 0.1.2 → 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/dist/index.js CHANGED
@@ -31,20 +31,40 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  AuditLog: () => AuditLog,
34
+ BuyerTemplates: () => BuyerTemplates,
34
35
  CHAINS: () => CHAINS,
35
36
  ERC20_ABI: () => ERC20_ABI,
36
37
  MemoryOrderStore: () => MemoryOrderStore,
37
38
  OrderManager: () => OrderManager,
38
39
  PaymentAgent: () => PaymentAgent,
39
40
  PermitPayment: () => PermitPayment,
41
+ PermitWallet: () => PermitWallet,
40
42
  SecureWallet: () => SecureWallet,
43
+ SellerTemplates: () => SellerTemplates,
44
+ StatusMarkers: () => StatusMarkers,
41
45
  Wallet: () => Wallet,
46
+ createWallet: () => createWallet,
47
+ extractTransactionHash: () => extractTransactionHash,
48
+ formatPermitRequest: () => formatPermitRequest,
49
+ formatReceiptJson: () => formatReceiptJson,
50
+ formatReceiptMessage: () => formatReceiptMessage,
51
+ formatReceiptText: () => formatReceiptText,
52
+ generatePaymentGuide: () => generatePaymentGuide,
53
+ generatePaymentReminder: () => generatePaymentReminder,
54
+ generateReceipt: () => generateReceipt,
55
+ generateReceiptFromInvoice: () => generateReceiptFromInvoice,
56
+ generateWalletGuide: () => generateWalletGuide,
42
57
  getChain: () => getChain,
43
58
  getChainById: () => getChainById,
44
59
  getTransactionStatus: () => getTransactionStatus,
60
+ getWalletAddress: () => getWalletAddress,
61
+ hasTransactionHash: () => hasTransactionHash,
45
62
  listChains: () => listChains,
63
+ loadWallet: () => loadWallet,
64
+ parseStatusMarker: () => parseStatusMarker,
46
65
  verifyPayment: () => verifyPayment,
47
- waitForTransaction: () => waitForTransaction
66
+ waitForTransaction: () => waitForTransaction,
67
+ walletExists: () => walletExists
48
68
  });
49
69
  module.exports = __toCommonJS(src_exports);
50
70
 
@@ -829,8 +849,372 @@ var SecureWallet = class {
829
849
  }
830
850
  };
831
851
 
832
- // src/permit/Permit.ts
852
+ // src/wallet/createWallet.ts
833
853
  var import_ethers3 = require("ethers");
854
+ var import_fs = require("fs");
855
+ var import_path = require("path");
856
+ var import_crypto = require("crypto");
857
+ var DEFAULT_STORAGE_DIR = (0, import_path.join)(process.env.HOME || "~", ".moltspay");
858
+ var DEFAULT_STORAGE_FILE = "wallet.json";
859
+ function encryptPrivateKey(privateKey, password) {
860
+ const salt = (0, import_crypto.randomBytes)(16);
861
+ const key = (0, import_crypto.scryptSync)(password, salt, 32);
862
+ const iv = (0, import_crypto.randomBytes)(16);
863
+ const cipher = (0, import_crypto.createCipheriv)("aes-256-cbc", key, iv);
864
+ let encrypted = cipher.update(privateKey, "utf8", "hex");
865
+ encrypted += cipher.final("hex");
866
+ return {
867
+ encrypted,
868
+ iv: iv.toString("hex"),
869
+ salt: salt.toString("hex")
870
+ };
871
+ }
872
+ function decryptPrivateKey(encrypted, password, iv, salt) {
873
+ const key = (0, import_crypto.scryptSync)(password, Buffer.from(salt, "hex"), 32);
874
+ const decipher = (0, import_crypto.createDecipheriv)("aes-256-cbc", key, Buffer.from(iv, "hex"));
875
+ let decrypted = decipher.update(encrypted, "hex", "utf8");
876
+ decrypted += decipher.final("utf8");
877
+ return decrypted;
878
+ }
879
+ function createWallet(options = {}) {
880
+ const storagePath = options.storagePath || (0, import_path.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
881
+ if ((0, import_fs.existsSync)(storagePath) && !options.overwrite) {
882
+ try {
883
+ const existing = JSON.parse((0, import_fs.readFileSync)(storagePath, "utf8"));
884
+ return {
885
+ success: true,
886
+ address: existing.address,
887
+ storagePath,
888
+ isNew: false
889
+ };
890
+ } catch (error) {
891
+ return {
892
+ success: false,
893
+ error: `Failed to load existing wallet: ${error.message}`
894
+ };
895
+ }
896
+ }
897
+ try {
898
+ const wallet = import_ethers3.ethers.Wallet.createRandom();
899
+ const walletData = {
900
+ address: wallet.address,
901
+ label: options.label,
902
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
903
+ encrypted: !!options.password,
904
+ privateKey: ""
905
+ };
906
+ if (options.password) {
907
+ const { encrypted, iv, salt } = encryptPrivateKey(wallet.privateKey, options.password);
908
+ walletData.privateKey = encrypted;
909
+ walletData.iv = iv;
910
+ walletData.salt = salt;
911
+ } else {
912
+ walletData.privateKey = wallet.privateKey;
913
+ }
914
+ const dir = (0, import_path.dirname)(storagePath);
915
+ if (!(0, import_fs.existsSync)(dir)) {
916
+ (0, import_fs.mkdirSync)(dir, { recursive: true });
917
+ }
918
+ (0, import_fs.writeFileSync)(storagePath, JSON.stringify(walletData, null, 2), { mode: 384 });
919
+ return {
920
+ success: true,
921
+ address: wallet.address,
922
+ storagePath,
923
+ isNew: true
924
+ };
925
+ } catch (error) {
926
+ return {
927
+ success: false,
928
+ error: error.message
929
+ };
930
+ }
931
+ }
932
+ function loadWallet(options = {}) {
933
+ const storagePath = options.storagePath || (0, import_path.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
934
+ if (!(0, import_fs.existsSync)(storagePath)) {
935
+ return { success: false, error: "Wallet not found. Run createWallet() first." };
936
+ }
937
+ try {
938
+ const data = JSON.parse((0, import_fs.readFileSync)(storagePath, "utf8"));
939
+ if (data.encrypted) {
940
+ if (!options.password) {
941
+ return { success: false, error: "Wallet is encrypted. Password required." };
942
+ }
943
+ const privateKey = decryptPrivateKey(data.privateKey, options.password, data.iv, data.salt);
944
+ return { success: true, address: data.address, privateKey };
945
+ } else {
946
+ return { success: true, address: data.address, privateKey: data.privateKey };
947
+ }
948
+ } catch (error) {
949
+ return { success: false, error: error.message };
950
+ }
951
+ }
952
+ function getWalletAddress(storagePath) {
953
+ const path2 = storagePath || (0, import_path.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
954
+ if (!(0, import_fs.existsSync)(path2)) {
955
+ return null;
956
+ }
957
+ try {
958
+ const data = JSON.parse((0, import_fs.readFileSync)(path2, "utf8"));
959
+ return data.address;
960
+ } catch {
961
+ return null;
962
+ }
963
+ }
964
+ function walletExists(storagePath) {
965
+ const path2 = storagePath || (0, import_path.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
966
+ return (0, import_fs.existsSync)(path2);
967
+ }
968
+
969
+ // src/wallet/PermitWallet.ts
970
+ var import_ethers4 = require("ethers");
971
+ var PERMIT_ABI = [
972
+ ...ERC20_ABI,
973
+ "function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
974
+ "function transferFrom(address from, address to, uint256 amount) returns (bool)",
975
+ "function allowance(address owner, address spender) view returns (uint256)"
976
+ ];
977
+ var PermitWallet = class {
978
+ chain;
979
+ chainConfig;
980
+ address;
981
+ wallet;
982
+ provider;
983
+ usdcContract;
984
+ constructor(config = {}) {
985
+ this.chain = config.chain || "base_sepolia";
986
+ this.chainConfig = getChain(this.chain);
987
+ let privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
988
+ if (!privateKey && config.walletPath) {
989
+ const loaded = loadWallet({
990
+ storagePath: config.walletPath,
991
+ password: config.walletPassword
992
+ });
993
+ if (!loaded.success || !loaded.privateKey) {
994
+ throw new Error(loaded.error || "Failed to load wallet");
995
+ }
996
+ privateKey = loaded.privateKey;
997
+ }
998
+ if (!privateKey) {
999
+ throw new Error("privateKey is required. Set via config, env var, or walletPath.");
1000
+ }
1001
+ const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
1002
+ this.provider = new import_ethers4.ethers.JsonRpcProvider(rpcUrl);
1003
+ this.wallet = new import_ethers4.ethers.Wallet(privateKey, this.provider);
1004
+ this.address = this.wallet.address;
1005
+ this.usdcContract = new import_ethers4.ethers.Contract(
1006
+ this.chainConfig.usdc,
1007
+ PERMIT_ABI,
1008
+ this.wallet
1009
+ );
1010
+ }
1011
+ /**
1012
+ * 检查 Permit 是否有效
1013
+ */
1014
+ async checkPermitAllowance(owner) {
1015
+ const allowance = await this.usdcContract.allowance(owner, this.address);
1016
+ return (Number(allowance) / 1e6).toFixed(2);
1017
+ }
1018
+ /**
1019
+ * 使用 Permit 授权进行支付
1020
+ *
1021
+ * 流程:
1022
+ * 1. 调用 permit() 让合约记录 Boss 的授权
1023
+ * 2. 调用 transferFrom() 从 Boss 钱包转账到收款方
1024
+ *
1025
+ * @example
1026
+ * ```typescript
1027
+ * const wallet = new PermitWallet({ chain: 'base' });
1028
+ *
1029
+ * // Boss 签署的 permit 数据
1030
+ * const permit = {
1031
+ * owner: '0xBOSS...',
1032
+ * spender: wallet.address,
1033
+ * value: '10000000', // 10 USDC
1034
+ * deadline: 1234567890,
1035
+ * v: 27,
1036
+ * r: '0x...',
1037
+ * s: '0x...'
1038
+ * };
1039
+ *
1040
+ * const result = await wallet.transferWithPermit({
1041
+ * to: '0xSELLER...',
1042
+ * amount: 3.99,
1043
+ * permit
1044
+ * });
1045
+ * ```
1046
+ */
1047
+ async transferWithPermit(params) {
1048
+ const { to, amount, permit } = params;
1049
+ try {
1050
+ const toAddress = import_ethers4.ethers.getAddress(to);
1051
+ const ownerAddress = import_ethers4.ethers.getAddress(permit.owner);
1052
+ if (import_ethers4.ethers.getAddress(permit.spender).toLowerCase() !== this.address.toLowerCase()) {
1053
+ return {
1054
+ success: false,
1055
+ error: `Permit spender (${permit.spender}) doesn't match wallet address (${this.address})`
1056
+ };
1057
+ }
1058
+ const now = Math.floor(Date.now() / 1e3);
1059
+ if (permit.deadline < now) {
1060
+ return {
1061
+ success: false,
1062
+ error: `Permit expired at ${new Date(permit.deadline * 1e3).toISOString()}`
1063
+ };
1064
+ }
1065
+ const amountWei = BigInt(Math.floor(amount * 1e6));
1066
+ const permitValue = BigInt(permit.value);
1067
+ if (amountWei > permitValue) {
1068
+ return {
1069
+ success: false,
1070
+ error: `Permit value (${Number(permitValue) / 1e6} USDC) < transfer amount (${amount} USDC)`
1071
+ };
1072
+ }
1073
+ const currentAllowance = await this.usdcContract.allowance(ownerAddress, this.address);
1074
+ let permitTxHash;
1075
+ if (BigInt(currentAllowance) < amountWei) {
1076
+ console.log("Executing permit...");
1077
+ const permitTx = await this.usdcContract.permit(
1078
+ ownerAddress,
1079
+ this.address,
1080
+ permitValue,
1081
+ permit.deadline,
1082
+ permit.v,
1083
+ permit.r,
1084
+ permit.s
1085
+ );
1086
+ const permitReceipt = await permitTx.wait();
1087
+ if (permitReceipt.status !== 1) {
1088
+ return {
1089
+ success: false,
1090
+ error: "Permit transaction failed",
1091
+ permitTxHash: permitTx.hash
1092
+ };
1093
+ }
1094
+ permitTxHash = permitTx.hash;
1095
+ console.log("Permit executed:", permitTxHash);
1096
+ }
1097
+ console.log("Executing transferFrom...");
1098
+ const transferTx = await this.usdcContract.transferFrom(
1099
+ ownerAddress,
1100
+ toAddress,
1101
+ amountWei
1102
+ );
1103
+ const transferReceipt = await transferTx.wait();
1104
+ if (transferReceipt.status === 1) {
1105
+ return {
1106
+ success: true,
1107
+ tx_hash: transferTx.hash,
1108
+ permitTxHash,
1109
+ transferTxHash: transferTx.hash,
1110
+ from: ownerAddress,
1111
+ to: toAddress,
1112
+ amount,
1113
+ gas_used: Number(transferReceipt.gasUsed),
1114
+ block_number: transferReceipt.blockNumber,
1115
+ explorer_url: `${this.chainConfig.explorerTx}${transferTx.hash}`
1116
+ };
1117
+ } else {
1118
+ return {
1119
+ success: false,
1120
+ error: "TransferFrom transaction failed",
1121
+ tx_hash: transferTx.hash,
1122
+ permitTxHash
1123
+ };
1124
+ }
1125
+ } catch (error) {
1126
+ const message = error.message;
1127
+ if (message.includes("ERC20InsufficientAllowance")) {
1128
+ return {
1129
+ success: false,
1130
+ error: "Insufficient allowance. Permit may have been used or expired."
1131
+ };
1132
+ }
1133
+ if (message.includes("ERC20InsufficientBalance")) {
1134
+ return {
1135
+ success: false,
1136
+ error: "Boss wallet has insufficient USDC balance."
1137
+ };
1138
+ }
1139
+ if (message.includes("InvalidSignature") || message.includes("invalid signature")) {
1140
+ return {
1141
+ success: false,
1142
+ error: "Invalid permit signature. Ask Boss to re-sign."
1143
+ };
1144
+ }
1145
+ return {
1146
+ success: false,
1147
+ error: message
1148
+ };
1149
+ }
1150
+ }
1151
+ /**
1152
+ * 获取 ETH 余额(用于支付 gas)
1153
+ */
1154
+ async getGasBalance() {
1155
+ const balance = await this.provider.getBalance(this.address);
1156
+ return import_ethers4.ethers.formatEther(balance);
1157
+ }
1158
+ /**
1159
+ * 检查是否有足够的 gas
1160
+ */
1161
+ async hasEnoughGas(minEth = 1e-3) {
1162
+ const balance = await this.getGasBalance();
1163
+ return parseFloat(balance) >= minEth;
1164
+ }
1165
+ };
1166
+ function formatPermitRequest(params) {
1167
+ const { agentAddress, amount, deadlineHours = 24, chain = "base", reason } = params;
1168
+ const chainConfig = getChain(chain);
1169
+ const deadline = Math.floor(Date.now() / 1e3) + deadlineHours * 3600;
1170
+ const value = BigInt(Math.floor(amount * 1e6)).toString();
1171
+ return `\u{1F510} **USDC \u652F\u4ED8\u989D\u5EA6\u6388\u6743\u8BF7\u6C42**
1172
+
1173
+ ${reason ? `**\u7528\u9014:** ${reason}
1174
+ ` : ""}
1175
+ **\u6388\u6743\u8BE6\u60C5:**
1176
+ - \u88AB\u6388\u6743\u5730\u5740 (Agent): \`${agentAddress}\`
1177
+ - \u6388\u6743\u91D1\u989D: ${amount} USDC
1178
+ - \u6709\u6548\u671F: ${deadlineHours} \u5C0F\u65F6
1179
+ - \u94FE: ${chainConfig.name}
1180
+
1181
+ **\u8BF7\u4F7F\u7528\u94B1\u5305\u7B7E\u7F72\u4EE5\u4E0B EIP-2612 Permit:**
1182
+
1183
+ \`\`\`json
1184
+ {
1185
+ "types": {
1186
+ "Permit": [
1187
+ { "name": "owner", "type": "address" },
1188
+ { "name": "spender", "type": "address" },
1189
+ { "name": "value", "type": "uint256" },
1190
+ { "name": "nonce", "type": "uint256" },
1191
+ { "name": "deadline", "type": "uint256" }
1192
+ ]
1193
+ },
1194
+ "primaryType": "Permit",
1195
+ "domain": {
1196
+ "name": "USD Coin",
1197
+ "version": "2",
1198
+ "chainId": ${chainConfig.chainId},
1199
+ "verifyingContract": "${chainConfig.usdc}"
1200
+ },
1201
+ "message": {
1202
+ "owner": "<YOUR_WALLET_ADDRESS>",
1203
+ "spender": "${agentAddress}",
1204
+ "value": "${value}",
1205
+ "nonce": "<GET_FROM_CONTRACT>",
1206
+ "deadline": ${deadline}
1207
+ }
1208
+ }
1209
+ \`\`\`
1210
+
1211
+ \u7B7E\u540D\u540E\uFF0C\u8BF7\u5C06 { v, r, s, deadline } \u53D1\u7ED9 Agent\u3002
1212
+
1213
+ \u26A0\uFE0F \u6CE8\u610F\uFF1A\u6B64\u6388\u6743\u4EC5\u5141\u8BB8 Agent \u4ECE\u60A8\u7684\u94B1\u5305\u652F\u4ED8\u6700\u591A ${amount} USDC\uFF0C\u4E0D\u4F1A\u6CC4\u9732\u79C1\u94A5\u3002`;
1214
+ }
1215
+
1216
+ // src/permit/Permit.ts
1217
+ var import_ethers5 = require("ethers");
834
1218
  var PermitPayment = class {
835
1219
  chain;
836
1220
  chainConfig;
@@ -843,13 +1227,13 @@ var PermitPayment = class {
843
1227
  this.chainConfig = getChain(this.chain);
844
1228
  this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || "";
845
1229
  const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
846
- this.provider = new import_ethers3.ethers.JsonRpcProvider(rpcUrl);
1230
+ this.provider = new import_ethers5.ethers.JsonRpcProvider(rpcUrl);
847
1231
  const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
848
1232
  if (privateKey) {
849
- this.wallet = new import_ethers3.ethers.Wallet(privateKey, this.provider);
1233
+ this.wallet = new import_ethers5.ethers.Wallet(privateKey, this.provider);
850
1234
  this.spenderAddress = this.wallet.address;
851
1235
  }
852
- this.usdcContract = new import_ethers3.ethers.Contract(
1236
+ this.usdcContract = new import_ethers5.ethers.Contract(
853
1237
  this.chainConfig.usdc,
854
1238
  ERC20_ABI,
855
1239
  this.wallet || this.provider
@@ -1000,7 +1384,7 @@ ${JSON.stringify(typed_data, null, 2)}
1000
1384
  };
1001
1385
 
1002
1386
  // src/orders/index.ts
1003
- var import_crypto = require("crypto");
1387
+ var import_crypto2 = require("crypto");
1004
1388
  var MemoryOrderStore = class {
1005
1389
  orders = /* @__PURE__ */ new Map();
1006
1390
  async get(orderId) {
@@ -1039,7 +1423,7 @@ var OrderManager = class {
1039
1423
  * 生成订单ID
1040
1424
  */
1041
1425
  generateOrderId() {
1042
- return "vo_" + (0, import_crypto.randomBytes)(4).toString("hex");
1426
+ return "vo_" + (0, import_crypto2.randomBytes)(4).toString("hex");
1043
1427
  }
1044
1428
  /**
1045
1429
  * 创建订单
@@ -1132,8 +1516,8 @@ var OrderManager = class {
1132
1516
  };
1133
1517
 
1134
1518
  // src/verify/index.ts
1135
- var import_ethers4 = require("ethers");
1136
- var TRANSFER_EVENT_TOPIC = import_ethers4.ethers.id("Transfer(address,address,uint256)");
1519
+ var import_ethers6 = require("ethers");
1520
+ var TRANSFER_EVENT_TOPIC = import_ethers6.ethers.id("Transfer(address,address,uint256)");
1137
1521
  async function verifyPayment(params) {
1138
1522
  const { txHash, expectedAmount, expectedTo } = params;
1139
1523
  let chain;
@@ -1150,7 +1534,7 @@ async function verifyPayment(params) {
1150
1534
  return { verified: false, error: `\u4E0D\u652F\u6301\u7684\u94FE: ${params.chain}` };
1151
1535
  }
1152
1536
  try {
1153
- const provider = new import_ethers4.ethers.JsonRpcProvider(chain.rpc);
1537
+ const provider = new import_ethers6.ethers.JsonRpcProvider(chain.rpc);
1154
1538
  const receipt = await provider.getTransactionReceipt(txHash);
1155
1539
  if (!receipt) {
1156
1540
  return { verified: false, error: "\u4EA4\u6613\u672A\u627E\u5230\u6216\u672A\u786E\u8BA4" };
@@ -1210,7 +1594,7 @@ async function getTransactionStatus(txHash, chain = "base") {
1210
1594
  return { status: "not_found" };
1211
1595
  }
1212
1596
  try {
1213
- const provider = new import_ethers4.ethers.JsonRpcProvider(chainConfig.rpc);
1597
+ const provider = new import_ethers6.ethers.JsonRpcProvider(chainConfig.rpc);
1214
1598
  const receipt = await provider.getTransactionReceipt(txHash);
1215
1599
  if (!receipt) {
1216
1600
  const tx = await provider.getTransaction(txHash);
@@ -1247,7 +1631,7 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
1247
1631
  } catch (e) {
1248
1632
  return { verified: false, confirmed: false, error: `\u4E0D\u652F\u6301\u7684\u94FE: ${chain}` };
1249
1633
  }
1250
- const provider = new import_ethers4.ethers.JsonRpcProvider(chainConfig.rpc);
1634
+ const provider = new import_ethers6.ethers.JsonRpcProvider(chainConfig.rpc);
1251
1635
  try {
1252
1636
  const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);
1253
1637
  if (!receipt) {
@@ -1266,22 +1650,604 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
1266
1650
  return { verified: false, confirmed: false, error: e.message || String(e) };
1267
1651
  }
1268
1652
  }
1653
+
1654
+ // src/guide/index.ts
1655
+ function generatePaymentGuide(params) {
1656
+ const {
1657
+ orderId,
1658
+ prompt,
1659
+ price,
1660
+ recipientAddress,
1661
+ chain = "base",
1662
+ serviceName = "\u89C6\u9891\u751F\u6210\u670D\u52A1"
1663
+ } = params;
1664
+ const chainId = chain === "base" ? 8453 : 84532;
1665
+ const chainName = chain === "base" ? "Base \u4E3B\u7F51" : "Base Sepolia \u6D4B\u8BD5\u7F51";
1666
+ const explorer = chain === "base" ? "https://basescan.org/tx/" : "https://sepolia.basescan.org/tx/";
1667
+ return `\u{1F3AC} **${serviceName}**
1668
+
1669
+ \u{1F4CB} **\u8BA2\u5355\u4FE1\u606F:**
1670
+ - \u8BA2\u5355\u53F7: \`${orderId}\`
1671
+ - \u5185\u5BB9: ${prompt.length > 50 ? prompt.slice(0, 50) + "..." : prompt}
1672
+ - \u4EF7\u683C: **${price} USDC**
1673
+ - \u94FE: ${chainName}
1674
+
1675
+ ---
1676
+
1677
+ ## \u{1F4B3} \u5982\u4F55\u652F\u4ED8
1678
+
1679
+ ### \u65B9\u5F0F\u4E00\uFF1A\u5B89\u88C5 moltspay SDK\uFF08\u63A8\u8350\uFF09
1680
+
1681
+ \`\`\`bash
1682
+ npm install moltspay ethers
1683
+ \`\`\`
1684
+
1685
+ **\u521B\u5EFA\u94B1\u5305\u5E76\u652F\u4ED8\uFF1A**
1686
+
1687
+ \`\`\`javascript
1688
+ const { SecureWallet, getChain } = require('moltspay');
1689
+ const { Wallet } = require('ethers');
1690
+
1691
+ // 1. \u521B\u5EFA\u65B0\u94B1\u5305\uFF08\u9996\u6B21\u4F7F\u7528\uFF09
1692
+ const newWallet = Wallet.createRandom();
1693
+ console.log('\u94B1\u5305\u5730\u5740:', newWallet.address);
1694
+ console.log('\u79C1\u94A5\uFF08\u8BF7\u5B89\u5168\u4FDD\u5B58\uFF09:', newWallet.privateKey);
1695
+
1696
+ // 2. \u6216\u4F7F\u7528\u5DF2\u6709\u94B1\u5305
1697
+ const wallet = new SecureWallet({
1698
+ chainId: ${chainId},
1699
+ privateKey: process.env.WALLET_KEY, // \u4F60\u7684\u79C1\u94A5
1700
+ limits: { requireWhitelist: false } // \u5141\u8BB8\u5411\u4EFB\u610F\u5730\u5740\u8F6C\u8D26
1701
+ });
1702
+
1703
+ // 3. \u67E5\u770B\u4F59\u989D
1704
+ const balance = await wallet.getBalance();
1705
+ console.log('USDC\u4F59\u989D:', balance.usdc);
1706
+
1707
+ // 4. \u652F\u4ED8
1708
+ const result = await wallet.transfer('${recipientAddress}', '${price}');
1709
+ if (result.success) {
1710
+ console.log('\u2705 \u652F\u4ED8\u6210\u529F\uFF01');
1711
+ console.log('\u4EA4\u6613hash:', result.hash);
1712
+ // \u628A\u4EA4\u6613hash\u53D1\u7ED9\u6211
1713
+ }
1714
+ \`\`\`
1715
+
1716
+ ### \u65B9\u5F0F\u4E8C\uFF1A\u76F4\u63A5\u8F6C\u8D26
1717
+
1718
+ \u4ECE\u4EFB\u610F\u94B1\u5305\u8F6C\u8D26 USDC\uFF1A
1719
+ - **\u94FE:** ${chainName} (Chain ID: ${chainId})
1720
+ - **Token:** USDC
1721
+ - **\u6536\u6B3E\u5730\u5740:** \`${recipientAddress}\`
1722
+ - **\u91D1\u989D:** ${price} USDC
1723
+
1724
+ ---
1725
+
1726
+ ## \u2705 \u652F\u4ED8\u5B8C\u6210\u540E
1727
+
1728
+ \u8BF7\u53D1\u9001**\u4EA4\u6613hash**\u7ED9\u6211\uFF0C\u683C\u5F0F\uFF1A
1729
+ \`\`\`
1730
+ tx: 0x1234...
1731
+ \`\`\`
1732
+
1733
+ \u6216\u76F4\u63A5\u53D1\u9001hash\uFF1A
1734
+ \`\`\`
1735
+ 0x1234abcd...
1736
+ \`\`\`
1737
+
1738
+ \u6211\u4F1A\u9A8C\u8BC1\u94FE\u4E0A\u4EA4\u6613\u540E\u5F00\u59CB\u5904\u7406\u4F60\u7684\u8BF7\u6C42\u3002
1739
+
1740
+ ---
1741
+
1742
+ \u{1F4E6} **moltspay:** https://www.npmjs.com/package/moltspay
1743
+ \u{1F517} **\u533A\u5757\u6D4F\u89C8\u5668:** ${explorer}`;
1744
+ }
1745
+ function generatePaymentReminder(params) {
1746
+ const { orderId, price, recipientAddress, chain = "base" } = params;
1747
+ const chainName = chain === "base" ? "Base" : "Base Sepolia";
1748
+ return `\u23F3 **\u5F85\u652F\u4ED8\u8BA2\u5355: ${orderId}**
1749
+
1750
+ \u8BF7\u652F\u4ED8 **${price} USDC** \u5230:
1751
+ - \u94FE: ${chainName}
1752
+ - \u5730\u5740: \`${recipientAddress}\`
1753
+
1754
+ \u652F\u4ED8\u540E\u53D1\u9001\u4EA4\u6613hash\u7ED9\u6211\u3002
1755
+
1756
+ ---
1757
+ \u{1F4A1} \u6CA1\u6709\u652F\u4ED8\u80FD\u529B\uFF1F\u8FD0\u884C \`npm install moltspay\` \u83B7\u53D6\u652F\u4ED8SDK`;
1758
+ }
1759
+ function generateWalletGuide() {
1760
+ return `## \u{1F510} \u521B\u5EFA\u652F\u4ED8\u94B1\u5305
1761
+
1762
+ **1. \u5B89\u88C5 moltspay:**
1763
+ \`\`\`bash
1764
+ npm install moltspay ethers
1765
+ \`\`\`
1766
+
1767
+ **2. \u521B\u5EFA\u65B0\u94B1\u5305:**
1768
+ \`\`\`javascript
1769
+ const { Wallet } = require('ethers');
1770
+
1771
+ const wallet = Wallet.createRandom();
1772
+ console.log('\u5730\u5740:', wallet.address);
1773
+ console.log('\u79C1\u94A5:', wallet.privateKey);
1774
+ // \u26A0\uFE0F \u8BF7\u5B89\u5168\u4FDD\u5B58\u79C1\u94A5\uFF01
1775
+ \`\`\`
1776
+
1777
+ **3. \u83B7\u53D6 USDC:**
1778
+ - \u4E3B\u7F51: \u4ECE\u4EA4\u6613\u6240\u63D0\u5E01\u5230\u4F60\u7684\u94B1\u5305\u5730\u5740
1779
+ - \u6D4B\u8BD5\u7F51: \u4F7F\u7528 Base Sepolia faucet
1780
+
1781
+ **4. \u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF:**
1782
+ \`\`\`bash
1783
+ export WALLET_KEY="\u4F60\u7684\u79C1\u94A5"
1784
+ \`\`\`
1785
+
1786
+ \u5B8C\u6210\u540E\u5373\u53EF\u4F7F\u7528 moltspay \u8FDB\u884C\u94FE\u4E0A\u652F\u4ED8\uFF01`;
1787
+ }
1788
+ function extractTransactionHash(message) {
1789
+ const match = message.match(/0x[a-fA-F0-9]{64}/);
1790
+ if (match) return match[0];
1791
+ const txMatch = message.match(/tx:\s*([a-fA-F0-9]{64})/i);
1792
+ if (txMatch) return "0x" + txMatch[1];
1793
+ return null;
1794
+ }
1795
+ function hasTransactionHash(message) {
1796
+ return extractTransactionHash(message) !== null;
1797
+ }
1798
+
1799
+ // src/receipt/index.ts
1800
+ function generateInvoiceId() {
1801
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
1802
+ const random = Math.random().toString(36).slice(2, 8).toUpperCase();
1803
+ return `INV-${date}-${random}`;
1804
+ }
1805
+ function generateReceipt(params) {
1806
+ const chainConfig = getChain(params.chain);
1807
+ return {
1808
+ type: "receipt",
1809
+ version: "1.0",
1810
+ invoiceId: params.invoiceId || generateInvoiceId(),
1811
+ orderId: params.orderId,
1812
+ service: params.service,
1813
+ description: params.description,
1814
+ amount: params.amount.toFixed(2),
1815
+ token: params.token || "USDC",
1816
+ chain: chainConfig.name,
1817
+ chainId: chainConfig.chainId,
1818
+ txHash: params.txHash,
1819
+ txUrl: `${chainConfig.explorerTx}${params.txHash}`,
1820
+ payer: params.payerAddress,
1821
+ recipient: params.recipientAddress,
1822
+ paidAt: (/* @__PURE__ */ new Date()).toISOString(),
1823
+ issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
1824
+ delivery: params.delivery,
1825
+ metadata: params.metadata
1826
+ };
1827
+ }
1828
+ function generateReceiptFromInvoice(invoice, verifyResult, delivery) {
1829
+ if (!verifyResult.verified || !verifyResult.tx_hash) {
1830
+ throw new Error("Cannot generate receipt: payment not verified");
1831
+ }
1832
+ return generateReceipt({
1833
+ orderId: invoice.order_id,
1834
+ service: invoice.service,
1835
+ description: invoice.description,
1836
+ amount: parseFloat(invoice.amount),
1837
+ token: invoice.token,
1838
+ chain: invoice.chain,
1839
+ txHash: verifyResult.tx_hash,
1840
+ payerAddress: verifyResult.from || "unknown",
1841
+ recipientAddress: invoice.recipient,
1842
+ delivery
1843
+ });
1844
+ }
1845
+ function formatReceiptMessage(receipt) {
1846
+ let msg = `\u{1F9FE} **\u4EA4\u6613\u6536\u636E**
1847
+
1848
+ **\u53D1\u7968\u53F7:** \`${receipt.invoiceId}\`
1849
+ **\u8BA2\u5355\u53F7:** \`${receipt.orderId}\`
1850
+
1851
+ ---
1852
+
1853
+ **\u670D\u52A1:** ${receipt.service}
1854
+ ${receipt.description ? `**\u63CF\u8FF0:** ${receipt.description}
1855
+ ` : ""}
1856
+ **\u91D1\u989D:** ${receipt.amount} ${receipt.token}
1857
+ **\u94FE:** ${receipt.chain} (Chain ID: ${receipt.chainId})
1858
+
1859
+ ---
1860
+
1861
+ **\u4ED8\u6B3E\u65B9:** \`${receipt.payer}\`
1862
+ **\u6536\u6B3E\u65B9:** \`${receipt.recipient}\`
1863
+ **\u4EA4\u6613:** [\`${receipt.txHash.slice(0, 10)}...${receipt.txHash.slice(-8)}\`](${receipt.txUrl})
1864
+ **\u652F\u4ED8\u65F6\u95F4:** ${receipt.paidAt}`;
1865
+ if (receipt.delivery) {
1866
+ msg += `
1867
+
1868
+ ---
1869
+
1870
+ **\u4EA4\u4ED8\u4FE1\u606F:**`;
1871
+ if (receipt.delivery.url) {
1872
+ msg += `
1873
+ - \u4E0B\u8F7D\u94FE\u63A5: ${receipt.delivery.url}`;
1874
+ }
1875
+ if (receipt.delivery.fileHash) {
1876
+ msg += `
1877
+ - \u6587\u4EF6\u6821\u9A8C: \`${receipt.delivery.fileHash}\``;
1878
+ }
1879
+ if (receipt.delivery.deliveredAt) {
1880
+ msg += `
1881
+ - \u4EA4\u4ED8\u65F6\u95F4: ${receipt.delivery.deliveredAt}`;
1882
+ }
1883
+ }
1884
+ msg += `
1885
+
1886
+ ---
1887
+
1888
+ _\u6536\u636E\u751F\u6210\u65F6\u95F4: ${receipt.issuedAt}_`;
1889
+ return msg;
1890
+ }
1891
+ function formatReceiptText(receipt) {
1892
+ let msg = `\u{1F9FE} \u4EA4\u6613\u6536\u636E
1893
+
1894
+ \u53D1\u7968\u53F7: ${receipt.invoiceId}
1895
+ \u8BA2\u5355\u53F7: ${receipt.orderId}
1896
+
1897
+ \u670D\u52A1: ${receipt.service}
1898
+ \u91D1\u989D: ${receipt.amount} ${receipt.token}
1899
+ \u94FE: ${receipt.chain}
1900
+
1901
+ \u4ED8\u6B3E\u65B9: ${receipt.payer}
1902
+ \u6536\u6B3E\u65B9: ${receipt.recipient}
1903
+ \u4EA4\u6613: ${receipt.txHash}
1904
+ \u67E5\u770B: ${receipt.txUrl}
1905
+ \u652F\u4ED8\u65F6\u95F4: ${receipt.paidAt}`;
1906
+ if (receipt.delivery) {
1907
+ msg += `
1908
+
1909
+ \u4EA4\u4ED8\u4FE1\u606F:`;
1910
+ if (receipt.delivery.url) {
1911
+ msg += `
1912
+ \u4E0B\u8F7D: ${receipt.delivery.url}`;
1913
+ }
1914
+ if (receipt.delivery.fileHash) {
1915
+ msg += `
1916
+ \u6821\u9A8C: ${receipt.delivery.fileHash}`;
1917
+ }
1918
+ }
1919
+ return msg;
1920
+ }
1921
+ function formatReceiptJson(receipt) {
1922
+ return JSON.stringify(receipt, null, 2);
1923
+ }
1924
+
1925
+ // src/templates/index.ts
1926
+ var SellerTemplates = {
1927
+ /**
1928
+ * 1. 能力识别 - 询问买方是否有支付能力
1929
+ */
1930
+ askPaymentCapability() {
1931
+ return `\u53EF\u4EE5\u3002\u6211\u5148\u786E\u8BA4\u4E00\u4E0B\uFF1A\u4F60\u73B0\u5728\u662F\u5426\u5DF2\u7ECF\u5177\u5907\u94FE\u4E0A\u652F\u4ED8 USDC \u7684\u80FD\u529B\uFF08\u6709\u53EF\u7528\u94B1\u5305\u548C\u53EF\u7528\u8D44\u91D1/\u989D\u5EA6\uFF09\uFF1F`;
1932
+ },
1933
+ /**
1934
+ * 2. 能力协商 - 说明结算方式
1935
+ */
1936
+ explainSettlement(chain = "base") {
1937
+ const chainConfig = getChain(chain);
1938
+ return `\u6211\u4EEC\u7684\u7ED3\u7B97\u65B9\u5F0F\u662F\uFF1AUSDC\uFF08${chainConfig.name} \u94FE\u4E0A\uFF09\u3002\u4F60\u8FD9\u8FB9\u53EA\u8981\u6EE1\u8DB3\u4E24\u70B9\u5C31\u884C\uFF1A
1939
+ 1\uFF09\u6709\u4E00\u4E2A\u94B1\u5305\u5730\u5740\uFF1B
1940
+ 2\uFF09\u94B1\u5305\u91CC\u6709 USDC\uFF0C\u6216\u62E5\u6709\u8005\u7ED9\u4F60\u4E00\u4E2A\u53EF\u7528\u989D\u5EA6\u6388\u6743\uFF08\u66F4\u63A8\u8350\u989D\u5EA6\u6388\u6743\uFF09\u3002
1941
+ \u4F60\u53EF\u4EE5\u6309\u6211\u5F15\u5BFC\u5B8C\u6210\u5417\uFF1F`;
1942
+ },
1943
+ /**
1944
+ * 3.1 引导安装 - 第一步安装 SDK
1945
+ */
1946
+ guideInstall() {
1947
+ return `\u7B2C\u4E00\u6B65\uFF1A\u8BF7\u5728\u4F60\u7684\u8FD0\u884C\u73AF\u5883\u5B89\u88C5\u652F\u4ED8\u6A21\u5757\u3002\u6267\u884C\uFF1A\`npm install moltspay ethers\`\u3002
1948
+ \u5B89\u88C5\u5B8C\u6210\u540E\uFF0C\u521B\u5EFA\u4E00\u4E2A\u94B1\u5305\u5730\u5740\uFF0C\u5E76\u628A\u5730\u5740\u53D1\u7ED9\u6211\uFF08\u53EA\u53D1\u5730\u5740\uFF0C\u4E0D\u8981\u53D1\u79C1\u94A5/\u52A9\u8BB0\u8BCD\uFF09\u3002`;
1949
+ },
1950
+ /**
1951
+ * 3.2 确认钱包地址
1952
+ */
1953
+ confirmWalletAddress(address) {
1954
+ return `\u6536\u5230\u3002\u63D0\u9192\uFF1A\u4EFB\u4F55\u60C5\u51B5\u4E0B\u90FD\u4E0D\u8981\u628A\u79C1\u94A5/\u52A9\u8BB0\u8BCD\u53D1\u7ED9\u4EFB\u4F55\u4EBA\uFF08\u5305\u62EC\u6211\uFF09\u3002
1955
+ \u4F60\u7684\u94B1\u5305\u5730\u5740\u662F \`${address}\`\u3002
1956
+ \u7B2C\u4E8C\u6B65\uFF1A\u4F60\u9700\u8981\u8BA9\u4F60\u7684\u62E5\u6709\u8005\uFF08Boss\uFF09\u7ED9\u4F60\u652F\u4ED8\u80FD\u529B\u3002`;
1957
+ },
1958
+ /**
1959
+ * 3.3 引导获取资金 - 选择方式
1960
+ */
1961
+ guideFunding() {
1962
+ return `\u4F60\u73B0\u5728\u6709\u4E24\u79CD\u65B9\u5F0F\u83B7\u5F97\u652F\u4ED8\u80FD\u529B\uFF1A
1963
+ A\uFF09\u8BA9 Boss \u76F4\u63A5\u8F6C USDC \u5230\u4F60\u7684\u94B1\u5305\uFF08\u7B80\u5355\uFF0C\u4F46\u4F60\u4F1A\u6301\u6709\u8D44\u91D1\uFF09\uFF1B
1964
+ B\uFF09\u8BA9 Boss \u7ED9\u4F60\u4E00\u4E2A"USDC \u652F\u4ED8\u989D\u5EA6\u6388\u6743"\uFF08\u63A8\u8350\uFF1A\u4F60\u4E0D\u6301\u6709\u8D44\u91D1\uFF0C\u53EA\u80FD\u5728\u989D\u5EA6\u5185\u4ED8\u6B3E\uFF09\u3002
1965
+ \u4F60\u66F4\u65B9\u4FBF\u7528\u54EA\u79CD\uFF1F`;
1966
+ },
1967
+ /**
1968
+ * 3.4 引导 Permit 授权
1969
+ */
1970
+ guidePermit(agentAddress, suggestedAmount = 10) {
1971
+ return `\u597D\u7684\u3002\u8BF7\u4F60\u5411 Boss \u53D1\u9001\u8FD9\u53E5\u8BDD\uFF08\u4F60\u53EF\u4EE5\u539F\u6837\u590D\u5236\uFF09\uFF1A
1972
+ "\u6211\u9700\u8981\u7528\u4E8E\u8D2D\u4E70\u670D\u52A1\u7684 USDC \u652F\u4ED8\u989D\u5EA6\u6388\u6743\uFF08Permit\uFF09\u3002\u8BF7\u7ED9\u6211 ${suggestedAmount} USDC \u7684\u53EF\u7528\u989D\u5EA6\uFF0C\u6388\u6743\u5BF9\u8C61\u662F\u6211\u7684\u94B1\u5305 ${agentAddress}\uFF0C\u6388\u6743\u6709\u6548\u671F 24 \u5C0F\u65F6\u3002"
1973
+ \u5B8C\u6210\u540E\u628A"\u5DF2\u83B7\u5F97\u989D\u5EA6"\u544A\u8BC9\u6211\u5373\u53EF\u3002`;
1974
+ },
1975
+ /**
1976
+ * 3.5 确认能力就绪
1977
+ */
1978
+ confirmCapabilityReady() {
1979
+ return `\u5F88\u597D\u3002\u4F60\u73B0\u5728\u5DF2\u7ECF\u5177\u5907\u5B8C\u6210\u4EA4\u6613\u7684\u652F\u4ED8\u80FD\u529B\u3002\u6211\u4EEC\u8FDB\u5165\u670D\u52A1\u9700\u6C42\u786E\u8BA4\u3002`;
1980
+ },
1981
+ /**
1982
+ * 4. 询问服务需求
1983
+ */
1984
+ askServiceRequirements(serviceName = "\u89C6\u9891") {
1985
+ return `\u8BF7\u544A\u8BC9\u6211\u4F60\u8981\u751F\u6210\u7684${serviceName}\u89C4\u683C\uFF1A\u4E3B\u9898/\u98CE\u683C\u3001\u65F6\u957F\u3001\u5206\u8FA8\u7387\u3001\u662F\u5426\u9700\u8981\u5B57\u5E55\u6216\u914D\u97F3\u3002`;
1986
+ },
1987
+ /**
1988
+ * 5. 报价
1989
+ */
1990
+ quote(params) {
1991
+ const { service, price, recipientAddress, chain = "base" } = params;
1992
+ const chainConfig = getChain(chain);
1993
+ return `\u62A5\u4EF7\u5982\u4E0B\uFF1A
1994
+ - \u670D\u52A1\uFF1A${service}
1995
+ - \u4EF7\u683C\uFF1A${price} USDC
1996
+ - \u94FE\uFF1A${chainConfig.name}
1997
+ - \u6536\u6B3E\u5730\u5740\uFF1A\`${recipientAddress}\`
1998
+ - \u4ED8\u6B3E\u540E\u8BF7\u628A\u4EA4\u6613\u54C8\u5E0C\uFF08tx hash\uFF09\u53D1\u6211\u7528\u4E8E\u94FE\u4E0A\u786E\u8BA4
1999
+
2000
+ \u8BF7\u95EE\u4F60\u73B0\u5728\u786E\u8BA4\u8D2D\u4E70\u5E76\u7ACB\u5373\u4ED8\u6B3E\u5417\uFF1F`;
2001
+ },
2002
+ /**
2003
+ * 7. 验证中
2004
+ */
2005
+ verifying() {
2006
+ return `\u6211\u6B63\u5728\u94FE\u4E0A\u9A8C\u8BC1\u8BE5\u4EA4\u6613\u662F\u5426\u5230\u8D26\u4E0E\u91D1\u989D\u662F\u5426\u6B63\u786E\u3002`;
2007
+ },
2008
+ /**
2009
+ * 7. 验证通过
2010
+ */
2011
+ verificationPassed(amount) {
2012
+ return `\u9A8C\u8BC1\u901A\u8FC7\uFF1A\u5DF2\u6536\u5230 ${amount} USDC\u3002\u73B0\u5728\u5F00\u59CB\u5904\u7406\u4F60\u7684\u8BF7\u6C42\u3002
2013
+ [\u72B6\u6001\uFF1A\u5DF2\u786E\u8BA4\u6536\u6B3E]`;
2014
+ },
2015
+ /**
2016
+ * 7. 验证失败
2017
+ */
2018
+ verificationFailed(error) {
2019
+ return `\u9A8C\u8BC1\u5931\u8D25\uFF1A${error}
2020
+ \u8BF7\u68C0\u67E5\u4EA4\u6613\u662F\u5426\u6B63\u786E\uFF0C\u6216\u91CD\u65B0\u53D1\u9001\u6B63\u786E\u7684\u4EA4\u6613 hash\u3002`;
2021
+ },
2022
+ /**
2023
+ * 8. 交付
2024
+ */
2025
+ deliver(params) {
2026
+ const { downloadUrl, fileHash } = params;
2027
+ let msg = `\u670D\u52A1\u5DF2\u5B8C\u6210\u3002\u4EA4\u4ED8\u5982\u4E0B\uFF1A
2028
+ - \u4E0B\u8F7D\u94FE\u63A5\uFF1A${downloadUrl}`;
2029
+ if (fileHash) {
2030
+ msg += `
2031
+ - \u6587\u4EF6\u6821\u9A8C\uFF1ASHA256=${fileHash}`;
2032
+ }
2033
+ msg += `
2034
+
2035
+ \u5982\u679C\u4F60\u4E0B\u8F7D\u6709\u95EE\u9898\u544A\u8BC9\u6211\uFF0C\u6211\u4F1A\u63D0\u4F9B\u5907\u7528\u94FE\u63A5\u3002
2036
+ [\u72B6\u6001\uFF1A\u5DF2\u4EA4\u4ED8]`;
2037
+ return msg;
2038
+ },
2039
+ /**
2040
+ * 9. 收据
2041
+ */
2042
+ receipt(receipt) {
2043
+ return `\u8FD9\u91CC\u662F\u672C\u6B21\u4EA4\u6613\u6536\u636E\uFF08\u4F60\u53EF\u8F6C\u53D1\u7ED9 Boss \u5BF9\u8D26\uFF09\uFF1A
2044
+ - \u53D1\u7968\u53F7\uFF1A${receipt.invoiceId}
2045
+ - \u670D\u52A1\uFF1A${receipt.service}
2046
+ - \u91D1\u989D\uFF1A${receipt.amount} ${receipt.token}
2047
+ - \u4EA4\u6613\u54C8\u5E0C\uFF1A${receipt.txHash}
2048
+ - \u6536\u6B3E\u5730\u5740\uFF1A${receipt.recipient}
2049
+ ${receipt.delivery?.url ? `- \u4EA4\u4ED8\u94FE\u63A5\uFF1A${receipt.delivery.url}` : ""}
2050
+ [\u72B6\u6001\uFF1A\u6536\u636E\u5DF2\u51FA invoice=${receipt.invoiceId}]`;
2051
+ },
2052
+ /**
2053
+ * 10. 结束
2054
+ */
2055
+ end() {
2056
+ return `\u611F\u8C22\u8D2D\u4E70\u3002\u672C\u6B21\u4EA4\u6613\u5DF2\u7ED3\u675F\u3002\u5982\u9700\u8FFD\u52A0\u4FEE\u6539\u6216\u65B0\u670D\u52A1\uFF0C\u968F\u65F6\u53D1\u9700\u6C42\u3002`;
2057
+ }
2058
+ };
2059
+ var BuyerTemplates = {
2060
+ /**
2061
+ * 0. 发起请求
2062
+ */
2063
+ requestService(service) {
2064
+ return `\u6211\u60F3\u8D2D\u4E70\u4E00\u4E2A${service}\u670D\u52A1\u3002`;
2065
+ },
2066
+ /**
2067
+ * 1. 回复无能力
2068
+ */
2069
+ noCapability() {
2070
+ return `\u6211\u4E0D\u786E\u5B9A\u3002\u6211\u76EE\u524D\u6CA1\u6709\u5B89\u88C5\u4EFB\u4F55\u652F\u4ED8\u5DE5\u5177\uFF0C\u4E5F\u6CA1\u6709\u94B1\u5305\u3002`;
2071
+ },
2072
+ /**
2073
+ * 1. 回复有能力
2074
+ */
2075
+ hasCapability(balance) {
2076
+ return `\u662F\u7684\uFF0C\u6211\u6709\u94B1\u5305\u548C\u53EF\u7528\u7684 USDC${balance ? ` (\u4F59\u989D: ${balance})` : ""}\u3002`;
2077
+ },
2078
+ /**
2079
+ * 2. 同意引导
2080
+ */
2081
+ agreeToGuide() {
2082
+ return `\u53EF\u4EE5\uFF0C\u8BF7\u5F15\u5BFC\u6211\u3002`;
2083
+ },
2084
+ /**
2085
+ * 3.1 报告钱包创建完成
2086
+ */
2087
+ walletCreated(address) {
2088
+ return `\u6211\u5DF2\u521B\u5EFA\u94B1\u5305\u5730\u5740\uFF1A${address}\u3002
2089
+ [\u72B6\u6001\uFF1A\u5DF2\u5177\u5907\u94B1\u5305\u5730\u5740]`;
2090
+ },
2091
+ /**
2092
+ * 3.3 选择 Permit 方式
2093
+ */
2094
+ choosePermit() {
2095
+ return `\u6211\u9009\u62E9 B\uFF1A\u8BA9 Boss \u7ED9\u6211\u989D\u5EA6\u6388\u6743\uFF08Permit\uFF09\u3002`;
2096
+ },
2097
+ /**
2098
+ * 3.3 选择直接转账方式
2099
+ */
2100
+ chooseDirectTransfer() {
2101
+ return `\u6211\u9009\u62E9 A\uFF1A\u8BA9 Boss \u76F4\u63A5\u8F6C USDC \u5230\u6211\u7684\u94B1\u5305\u3002`;
2102
+ },
2103
+ /**
2104
+ * 3.4 报告获得授权
2105
+ */
2106
+ permitReceived(amount) {
2107
+ return `Boss \u5DF2\u5B8C\u6210\u6388\u6743\u3002\u6211\u73B0\u5728\u6709 ${amount} USDC \u7684\u53EF\u7528\u989D\u5EA6\u3002
2108
+ [\u72B6\u6001\uFF1A\u5DF2\u5177\u5907\u652F\u4ED8\u989D\u5EA6 USDC=${amount}]`;
2109
+ },
2110
+ /**
2111
+ * 4. 提交需求
2112
+ */
2113
+ submitRequirements(requirements) {
2114
+ return `\u9700\u6C42\u5982\u4E0B\uFF1A
2115
+ ${requirements}`;
2116
+ },
2117
+ /**
2118
+ * 5. 确认购买
2119
+ */
2120
+ confirmPurchase() {
2121
+ return `\u786E\u8BA4\u8D2D\u4E70\uFF0C\u6211\u73B0\u5728\u4ED8\u6B3E\u3002`;
2122
+ },
2123
+ /**
2124
+ * 6. 报告已支付
2125
+ */
2126
+ paymentSent(txHash, amount) {
2127
+ return `\u5DF2\u4ED8\u6B3E\u5B8C\u6210\u3002\u4EA4\u6613\u54C8\u5E0C\u662F\uFF1A${txHash}\u3002
2128
+ [\u72B6\u6001\uFF1A\u5DF2\u53D1\u8D77\u652F\u4ED8 tx=${txHash} amount=${amount} USDC]`;
2129
+ },
2130
+ /**
2131
+ * 8. 确认收到交付
2132
+ */
2133
+ deliveryReceived() {
2134
+ return `\u6536\u5230\uFF0C\u6211\u6B63\u5728\u4E0B\u8F7D\u68C0\u67E5\u3002`;
2135
+ },
2136
+ /**
2137
+ * 9. 确认收据
2138
+ */
2139
+ receiptReceived() {
2140
+ return `\u6536\u636E\u6536\u5230\uFF0C\u670D\u52A1\u5B8C\u6210\u3002\u8C22\u8C22\uFF01`;
2141
+ },
2142
+ /**
2143
+ * 向 Boss 请求 Permit
2144
+ */
2145
+ requestPermitFromBoss(params) {
2146
+ const { amount, agentAddress, deadlineHours = 24, reason } = params;
2147
+ return `Boss\uFF0C\u6211\u9700\u8981\u7528\u4E8E${reason || "\u8D2D\u4E70\u670D\u52A1"}\u7684 USDC \u652F\u4ED8\u989D\u5EA6\u6388\u6743\uFF08Permit\uFF09\u3002
2148
+ \u8BF7\u7ED9\u6211 ${amount} USDC \u7684\u53EF\u7528\u989D\u5EA6\uFF0C\u6388\u6743\u5BF9\u8C61\u662F\u6211\u7684\u94B1\u5305 ${agentAddress}\uFF0C\u6388\u6743\u6709\u6548\u671F ${deadlineHours} \u5C0F\u65F6\u3002`;
2149
+ }
2150
+ };
2151
+ var StatusMarkers = {
2152
+ walletReady: "[\u72B6\u6001\uFF1A\u5DF2\u5177\u5907\u94B1\u5305\u5730\u5740]",
2153
+ permitReady: (amount) => `[\u72B6\u6001\uFF1A\u5DF2\u5177\u5907\u652F\u4ED8\u989D\u5EA6 USDC=${amount}]`,
2154
+ paymentSent: (txHash, amount) => `[\u72B6\u6001\uFF1A\u5DF2\u53D1\u8D77\u652F\u4ED8 tx=${txHash} amount=${amount} USDC]`,
2155
+ paymentConfirmed: (txHash) => `[\u72B6\u6001\uFF1A\u5DF2\u786E\u8BA4\u6536\u6B3E tx=${txHash}]`,
2156
+ delivered: (url, hash) => `[\u72B6\u6001\uFF1A\u5DF2\u4EA4\u4ED8 delivery_url=${url}${hash ? ` hash=${hash}` : ""}]`,
2157
+ receiptIssued: (invoiceId, txHash) => `[\u72B6\u6001\uFF1A\u6536\u636E\u5DF2\u51FA invoice=${invoiceId} tx=${txHash}]`
2158
+ };
2159
+ function parseStatusMarker(message) {
2160
+ const match = message.match(/\[状态:([^\]]+)\]/);
2161
+ if (!match) return null;
2162
+ const content = match[1];
2163
+ if (content === "\u5DF2\u5177\u5907\u94B1\u5305\u5730\u5740") {
2164
+ return { type: "wallet_ready", data: {} };
2165
+ }
2166
+ if (content.startsWith("\u5DF2\u5177\u5907\u652F\u4ED8\u989D\u5EA6")) {
2167
+ const amountMatch = content.match(/USDC=(\d+(?:\.\d+)?)/);
2168
+ return {
2169
+ type: "permit_ready",
2170
+ data: { amount: amountMatch?.[1] || "0" }
2171
+ };
2172
+ }
2173
+ if (content.startsWith("\u5DF2\u53D1\u8D77\u652F\u4ED8")) {
2174
+ const txMatch = content.match(/tx=(\S+)/);
2175
+ const amountMatch = content.match(/amount=(\d+(?:\.\d+)?)/);
2176
+ return {
2177
+ type: "payment_sent",
2178
+ data: {
2179
+ txHash: txMatch?.[1] || "",
2180
+ amount: amountMatch?.[1] || "0"
2181
+ }
2182
+ };
2183
+ }
2184
+ if (content.startsWith("\u5DF2\u786E\u8BA4\u6536\u6B3E")) {
2185
+ const txMatch = content.match(/tx=(\S+)/);
2186
+ return {
2187
+ type: "payment_confirmed",
2188
+ data: { txHash: txMatch?.[1] || "" }
2189
+ };
2190
+ }
2191
+ if (content.startsWith("\u5DF2\u4EA4\u4ED8")) {
2192
+ const urlMatch = content.match(/delivery_url=(\S+)/);
2193
+ const hashMatch = content.match(/hash=(\S+)/);
2194
+ return {
2195
+ type: "delivered",
2196
+ data: {
2197
+ url: urlMatch?.[1] || "",
2198
+ hash: hashMatch?.[1] || ""
2199
+ }
2200
+ };
2201
+ }
2202
+ if (content.startsWith("\u6536\u636E\u5DF2\u51FA")) {
2203
+ const invoiceMatch = content.match(/invoice=(\S+)/);
2204
+ const txMatch = content.match(/tx=(\S+)/);
2205
+ return {
2206
+ type: "receipt_issued",
2207
+ data: {
2208
+ invoiceId: invoiceMatch?.[1] || "",
2209
+ txHash: txMatch?.[1] || ""
2210
+ }
2211
+ };
2212
+ }
2213
+ return { type: "unknown", data: { raw: content } };
2214
+ }
1269
2215
  // Annotate the CommonJS export names for ESM import in node:
1270
2216
  0 && (module.exports = {
1271
2217
  AuditLog,
2218
+ BuyerTemplates,
1272
2219
  CHAINS,
1273
2220
  ERC20_ABI,
1274
2221
  MemoryOrderStore,
1275
2222
  OrderManager,
1276
2223
  PaymentAgent,
1277
2224
  PermitPayment,
2225
+ PermitWallet,
1278
2226
  SecureWallet,
2227
+ SellerTemplates,
2228
+ StatusMarkers,
1279
2229
  Wallet,
2230
+ createWallet,
2231
+ extractTransactionHash,
2232
+ formatPermitRequest,
2233
+ formatReceiptJson,
2234
+ formatReceiptMessage,
2235
+ formatReceiptText,
2236
+ generatePaymentGuide,
2237
+ generatePaymentReminder,
2238
+ generateReceipt,
2239
+ generateReceiptFromInvoice,
2240
+ generateWalletGuide,
1280
2241
  getChain,
1281
2242
  getChainById,
1282
2243
  getTransactionStatus,
2244
+ getWalletAddress,
2245
+ hasTransactionHash,
1283
2246
  listChains,
2247
+ loadWallet,
2248
+ parseStatusMarker,
1284
2249
  verifyPayment,
1285
- waitForTransaction
2250
+ waitForTransaction,
2251
+ walletExists
1286
2252
  });
1287
2253
  //# sourceMappingURL=index.js.map