astra-modal-test 1.0.8 → 1.0.10

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.
Files changed (112) hide show
  1. package/dist/{SwapController-CDa6lMYy.js → SwapController-DyormRqe.js} +1 -1
  2. package/dist/{add-xF_ArAzf.js → add-C1zIRxeS.js} +1 -1
  3. package/dist/{all-wallets-Ce6u9aar.js → all-wallets-5a2U9fLw.js} +1 -1
  4. package/dist/{app-store-BSB6s3ao.js → app-store-2IKrZeLe.js} +1 -1
  5. package/dist/{apple-5FMqwZ50.js → apple-DH9ESSKX.js} +1 -1
  6. package/dist/{arrow-bottom-UI4iKSwb.js → arrow-bottom-BxAPS43J.js} +1 -1
  7. package/dist/{arrow-bottom-circle-jiPRKg_i.js → arrow-bottom-circle-Cy5Gjca4.js} +1 -1
  8. package/dist/{arrow-left-vWFYC_Uy.js → arrow-left-CBX7JaHB.js} +1 -1
  9. package/dist/{arrow-right-RDYl_d9f.js → arrow-right-G72bt1-M.js} +1 -1
  10. package/dist/{arrow-top-CFdymIsb.js → arrow-top-DCkQG0Dq.js} +1 -1
  11. package/dist/astra-sdk.es.js +1 -1
  12. package/dist/{bank-B6Ywh_tB.js → bank-FNxAUs8r.js} +1 -1
  13. package/dist/{bin-Das2naOJ.js → bin-B-c2CIPW.js} +1 -1
  14. package/dist/{bitcoin-cEJe5mt0.js → bitcoin-jk4NLDu1.js} +1 -1
  15. package/dist/{browser-BdXpj-Hv.js → browser-D6w0J78l.js} +1 -1
  16. package/dist/{card-C1ElQWBR.js → card-BLWRKU-r.js} +1 -1
  17. package/dist/{ccip-xelHOcyN.js → ccip-DkYvh7hg.js} +1 -1
  18. package/dist/{checkmark-CoMIwXfk.js → checkmark-C1pTfaGr.js} +1 -1
  19. package/dist/{checkmark-bold-Cw14vvfX.js → checkmark-bold-UzogCu8g.js} +1 -1
  20. package/dist/{chevron-bottom-BIpRQPXG.js → chevron-bottom-w_rMAO7x.js} +1 -1
  21. package/dist/{chevron-left-Ba9KSrTt.js → chevron-left-DGNJGxiP.js} +1 -1
  22. package/dist/{chevron-right-DiRY5RBl.js → chevron-right-VFQCvCyG.js} +1 -1
  23. package/dist/{chevron-top-D63uD3sz.js → chevron-top-DVhFmsKp.js} +1 -1
  24. package/dist/{chrome-store-CDMywF6G.js → chrome-store-BkYX3All.js} +1 -1
  25. package/dist/{circle-RKQpGmr7.js → circle-B1A3j4eP.js} +1 -1
  26. package/dist/{clock-DLLB40xi.js → clock-BKr-VHDU.js} +1 -1
  27. package/dist/{close-r9wJQIs6.js → close-BEacRQ8Q.js} +1 -1
  28. package/dist/{coinPlaceholder-DwEAr3DY.js → coinPlaceholder-0ZwtMAHl.js} +1 -1
  29. package/dist/{compass-DNvmj1tj.js → compass-pulK-BFi.js} +1 -1
  30. package/dist/{copy-CMAbqfSd.js → copy-MWCQE0T4.js} +1 -1
  31. package/dist/{cursor-C1UG5uSa.js → cursor-C2GVfUuM.js} +1 -1
  32. package/dist/{cursor-transparent-gRO-kv14.js → cursor-transparent-Co_5p0du.js} +1 -1
  33. package/dist/{desktop-USBykYXc.js → desktop-C91EoSqM.js} +1 -1
  34. package/dist/{disconnect-gXgOnS1O.js → disconnect-BWg1-rml.js} +1 -1
  35. package/dist/{discord-BoVW92xx.js → discord-Bi0Bfa_e.js} +1 -1
  36. package/dist/{email-MUGxDZyn.js → email-U2WCRPFh.js} +1 -1
  37. package/dist/{embedded-wallet-wtFatZbn.js → embedded-wallet-B6P0kU9A.js} +1 -1
  38. package/dist/{ethereum-CrlKIxWS.js → ethereum-BeZyayQW.js} +1 -1
  39. package/dist/{etherscan-B7rldLcE.js → etherscan-BQTsufjv.js} +1 -1
  40. package/dist/{exclamation-triangle-DkWjxCXA.js → exclamation-triangle-JT-YKNXX.js} +1 -1
  41. package/dist/{extension-Cc-fkUZ4.js → extension-TnYLHoFA.js} +1 -1
  42. package/dist/{external-link-BGpONWeJ.js → external-link-Dhgai9sc.js} +1 -1
  43. package/dist/{facebook-WtT1OR1K.js → facebook-C6XFGRDw.js} +1 -1
  44. package/dist/{farcaster-XYlVovPm.js → farcaster-CvYbxZQq.js} +1 -1
  45. package/dist/{filters-BHJQ4Xxm.js → filters-DwVRjAav.js} +1 -1
  46. package/dist/{github-BrLDodDi.js → github-BVZSx-z9.js} +1 -1
  47. package/dist/{google-DyLvy2-l.js → google-NbJiQLc5.js} +1 -1
  48. package/dist/{help-circle-DSrnsOz5.js → help-circle-Cum2UOMJ.js} +1 -1
  49. package/dist/{id-hq9eJ4Qc.js → id-kRR6YgVc.js} +1 -1
  50. package/dist/{image-BSNbjEuh.js → image-BWUCRAmp.js} +1 -1
  51. package/dist/{index-DLgq0XCK.js → index-2vYoun4O.js} +5328 -5267
  52. package/dist/{index-BSaELrPQ.js → index-BDE-2VTp.js} +6 -6
  53. package/dist/{index-CjuYAla0.js → index-BZZHE-1t.js} +1 -1
  54. package/dist/{index-BBtSm4ym.js → index-BjLIiJQa.js} +1 -1
  55. package/dist/{index-1xpIFQ10.js → index-CIr4zlVp.js} +1 -1
  56. package/dist/{index-DKXwTi_4.js → index-D-T7kk3G.js} +1 -1
  57. package/dist/{index-j1CHbogh.js → index-DQ5AZLMt.js} +1 -1
  58. package/dist/{index-D0yTNAa2.js → index-DSX3HrTS.js} +1 -1
  59. package/dist/{index-DAggWyCU.js → index-Dq0LIBEh.js} +1 -1
  60. package/dist/{index-BAAVr7gv.js → index-RFYbqmu0.js} +1 -1
  61. package/dist/{info-Dwz6bnKI.js → info-Br-SBtj3.js} +1 -1
  62. package/dist/{info-circle-Dlv6yGm-.js → info-circle-Ew4RoR_Q.js} +1 -1
  63. package/dist/{lightbulb-B22koKw9.js → lightbulb-BRBVOE_b.js} +1 -1
  64. package/dist/{mail-CTfIfuUf.js → mail-Dzi4AncY.js} +1 -1
  65. package/dist/{mobile-CXKePK9r.js → mobile-BGGxQ5be.js} +1 -1
  66. package/dist/{more-BAc1_O1l.js → more-BmNaKbYJ.js} +1 -1
  67. package/dist/{network-placeholder-DQimEkgX.js → network-placeholder-EMiMf4q1.js} +1 -1
  68. package/dist/{nftPlaceholder-TmxwESKA.js → nftPlaceholder-CvSqy3Sd.js} +1 -1
  69. package/dist/{off-BEIz28wS.js → off-DF9uz0Nc.js} +1 -1
  70. package/dist/{onramp-CDGUJxkp.js → onramp-cKzTmKku.js} +1 -1
  71. package/dist/{play-store-7v3FRGPC.js → play-store-CGxW4MgL.js} +1 -1
  72. package/dist/{plus-DgWZStdP.js → plus-CQ6wWkN0.js} +1 -1
  73. package/dist/{qr-code-Za-zeUy1.js → qr-code-VBqx9nAF.js} +1 -1
  74. package/dist/{receive-BvZ2zsvF.js → receive-CVzkHmKR.js} +1 -1
  75. package/dist/{recycle-horizontal-D6nbmPsy.js → recycle-horizontal-Oq1YtvUx.js} +1 -1
  76. package/dist/{refresh-CB3gA1em.js → refresh-BDlGAzmY.js} +1 -1
  77. package/dist/{reown-logo-xKt4nApt.js → reown-logo-BlIpXIlG.js} +1 -1
  78. package/dist/{search-B5scACGZ.js → search-DfmCmp0m.js} +1 -1
  79. package/dist/{secp256k1-BS_H6cc8.js → secp256k1-CsKSDHNi.js} +1 -1
  80. package/dist/{send-CPH_rRYi.js → send-BXudz514.js} +1 -1
  81. package/dist/{send-D1BZuohM.js → send-Cz0L5LmE.js} +3 -3
  82. package/dist/{socials-BJX4OF48.js → socials-CDOh8MRf.js} +1 -1
  83. package/dist/{solana-T53kr1IG.js → solana-CbiyOE-8.js} +1 -1
  84. package/dist/{swapHorizontal-CaqxaS7f.js → swapHorizontal-DyU1TH_e.js} +1 -1
  85. package/dist/{swapHorizontalBold-Sig9ZLtj.js → swapHorizontalBold-CGXW7Ocj.js} +1 -1
  86. package/dist/{swapHorizontalMedium-BRczHHwL.js → swapHorizontalMedium-2KTcj67d.js} +1 -1
  87. package/dist/{swapHorizontalRoundedBold-BpdCU9Bp.js → swapHorizontalRoundedBold-TxFtmmda.js} +1 -1
  88. package/dist/{swapVertical-vOPpeKvX.js → swapVertical-BKD6lxM3.js} +1 -1
  89. package/dist/{swaps-BLkPFWh6.js → swaps-BuGsEQaI.js} +3 -3
  90. package/dist/{telegram-muGVhw5Y.js → telegram-CAsl9DeG.js} +1 -1
  91. package/dist/{three-dots-BsyVBW01.js → three-dots-BoE2aHZi.js} +1 -1
  92. package/dist/{transactions-BOv1jcPD.js → transactions-C1NtsnD6.js} +1 -1
  93. package/dist/{twitch-DnFvNzNv.js → twitch-CvkZZxgT.js} +1 -1
  94. package/dist/{twitterIcon--wOgsps0.js → twitterIcon-CrhnOl_O.js} +1 -1
  95. package/dist/{ui-BUY2qZV0.js → ui-BJcuThPA.js} +2 -2
  96. package/dist/{user-Y3D7wRs8.js → user-BZRWUXG7.js} +1 -1
  97. package/dist/{verify-filled-Dy1sirT4.js → verify-filled-X_8-BhMk.js} +1 -1
  98. package/dist/{verify-C3Wv-vWi.js → verify-y9F4DcJ4.js} +1 -1
  99. package/dist/{w3m-modal-Bw-dR_fI.js → w3m-modal-BX--v1Nc.js} +2 -2
  100. package/dist/{wallet-BcaN7X2R.js → wallet-CIaVVkjQ.js} +1 -1
  101. package/dist/{wallet-placeholder-JKwOItCz.js → wallet-placeholder-Cq1ofde1.js} +1 -1
  102. package/dist/{walletconnect-DT2QhxnA.js → walletconnect-CINzSCJ3.js} +1 -1
  103. package/dist/{warning-circle-D-vheGlH.js → warning-circle-BvBNhMKH.js} +1 -1
  104. package/dist/{x-mark-BaQ2cTjZ.js → x-mark-DEmnBt6u.js} +1 -1
  105. package/dist/{x-DzCcyciF.js → x-xHY7JehW.js} +1 -1
  106. package/package.json +1 -1
  107. package/src/comps/ToLightning.jsx +41 -5
  108. package/src/comps/ToToken.jsx +40 -4
  109. package/src/hooks/useLspApi.js +1 -1
  110. package/src/index.jsx +9 -1
  111. package/src/main.jsx +7 -4
  112. package/src/utils/index.js +128 -9
@@ -89,7 +89,6 @@ function ToToken({ messageApi }) {
89
89
  setAstraModalShow,
90
90
  astraModalShow,
91
91
  } = useStore();
92
-
93
92
  const [sendInvoice, setSendInvoice] = useState("");
94
93
  const [tx, setTx] = useState("");
95
94
  const account = useAccount();
@@ -101,10 +100,27 @@ function ToToken({ messageApi }) {
101
100
 
102
101
  const { switchChain } = useSwitchChain();
103
102
 
104
- const filterdAssetPairs = useMemo(() => {
105
- return allAssetPairs.filter((pair) => {
103
+ const { filterdAssetPairs, validationError } = useMemo(() => {
104
+ const filtered = allAssetPairs.filter((pair) => {
106
105
  return pair.asset.assetId === sendArgs.assetId;
107
106
  });
107
+
108
+ // 校验资产是否支持
109
+ let error = null;
110
+ if (allAssetPairs.length > 0 && filtered.length === 0) {
111
+ const supportedAssets = allAssetPairs
112
+ .map(
113
+ (pair) =>
114
+ `${pair.asset.name} (${pair.asset.assetId.substring(0, 8)}...)`
115
+ )
116
+ .join(", ");
117
+ error = `Asset "${sendArgs.assetId.substring(
118
+ 0,
119
+ 8
120
+ )}..." is not supported. Supported assets: ${supportedAssets}`;
121
+ }
122
+
123
+ return { filterdAssetPairs: filtered, validationError: error };
108
124
  }, [allAssetPairs, sendArgs.assetId]);
109
125
  // console.log("🚀 ~ ToLightning ~ allAssetPairs:", allAssetPairs, receiveArgs);
110
126
  const { reserveInfo, loading: reserveInfoLoading } = useGetReserveInfo(
@@ -328,7 +344,7 @@ function ToToken({ messageApi }) {
328
344
  type="primary"
329
345
  htmlType="submit"
330
346
  loading={submitLoading}
331
- disabled={isInvoiceExpired}
347
+ disabled={isInvoiceExpired || validationError}
332
348
  >
333
349
  <span>{submitLoading ? "Waiting for Confirmation" : "Withdraw"}</span>
334
350
  <img src={IconArrowRight} alt="" />
@@ -346,6 +362,7 @@ function ToToken({ messageApi }) {
346
362
  submitLoading,
347
363
  targetNetwork?.blockExplorers?.default.url,
348
364
  tx,
365
+ validationError,
349
366
  ]);
350
367
 
351
368
  const onExpired = useCallback(() => {
@@ -356,12 +373,31 @@ function ToToken({ messageApi }) {
356
373
  if (filterdAssetPairs?.length > 0) {
357
374
  setCurrentAssetPair(filterdAssetPairs[0]);
358
375
  form.setFieldValue("received", filterdAssetPairs?.[0]?.pairId);
376
+ } else {
377
+ setCurrentAssetPair(null);
378
+ form.setFieldValue("received", "");
359
379
  }
360
380
  // eslint-disable-next-line react-hooks/exhaustive-deps
361
381
  }, [filterdAssetPairs, form]);
362
382
  return (
363
383
  <WrapperToLightning>
364
384
  <Spin spinning={reserveInfoLoading}>
385
+ {validationError && (
386
+ <div
387
+ style={{
388
+ padding: "12px 16px",
389
+ marginBottom: "16px",
390
+ borderRadius: "8px",
391
+ background: "rgba(255, 77, 79, 0.1)",
392
+ border: "1px solid rgba(255, 77, 79, 0.3)",
393
+ color: "#ff4d4f",
394
+ fontSize: "14px",
395
+ lineHeight: "1.5",
396
+ }}
397
+ >
398
+ ⚠️ {validationError}
399
+ </div>
400
+ )}
365
401
  <Form
366
402
  name="basic"
367
403
  form={form}
@@ -52,7 +52,7 @@ export const useGetReserveInfo = (targetNetwork, currentAssetPair) => {
52
52
 
53
53
  return {
54
54
  reserveInfo: data?.data,
55
- loading,
55
+ loading: pairId ? loading : false,
56
56
  refresh,
57
57
  };
58
58
  };
package/src/index.jsx CHANGED
@@ -28,7 +28,8 @@ const defaultMetadata = {
28
28
  };
29
29
 
30
30
  const API_URL_MAP = {
31
- development: "https://devof-astralsp.unift.xyz/",
31
+ // development: "https://devof-astralsp.unift.xyz/",
32
+ development: "https://devof-nodeflow-bridge-api.unift.xyz/",
32
33
  production: "https://api.astra-labs.io/",
33
34
  };
34
35
  // 3. Set the networks
@@ -129,12 +130,16 @@ export const AstraModal = AstraDialog;
129
130
  export function astraReceive({ invoice, assetId }) {
130
131
  //evm2lightning
131
132
  const store = useStore;
133
+
134
+ // 校验将在组件内部进行(因为需要等待 allAssetPairs 加载)
135
+ // 这里只设置参数,由 ToLightning 组件负责校验和显示错误
132
136
  store.setState(() => ({
133
137
  astraModalShow: true,
134
138
  receiveArgs: { invoice, assetId },
135
139
  modalDisplayType: MODAL_DISPLAY_TYPE.TO_LIGHTNING,
136
140
  }));
137
141
  }
142
+
138
143
  // eslint-disable-next-line react-refresh/only-export-components
139
144
  export function astraSend({
140
145
  amount,
@@ -144,6 +149,9 @@ export function astraSend({
144
149
  }) {
145
150
  // lightning2evm
146
151
  const store = useStore;
152
+
153
+ // 校验将在组件内部进行(因为需要等待 allAssetPairs 加载)
154
+ // 这里只设置参数,由 ToToken 组件负责校验和显示错误
147
155
  store.setState(() => ({
148
156
  astraModalShow: true,
149
157
  sendArgs: { amount, assetId, waitConfirm },
package/src/main.jsx CHANGED
@@ -20,10 +20,13 @@ createRoot(document.getElementById("root")).render(
20
20
  <Button
21
21
  onClick={() => {
22
22
  astraReceive({
23
- assetId:
24
- "f7ac99f2c068f1157c787012f50cb043437505c309c6d8685e135cd8481b1e9d",
23
+ assetId: "rgb:kmbI~9N8-ruOAnr5-GXZ6ylm-ZhPrR3N-_PydETF-ZyC1jXQ",
25
24
  invoice:
26
- "lnbcrt100u1p5gw8avpp5jnqgevzt4dzq4q2f74nfe2ms5fzmuyzj3svre4zlj0dsxyq0cknsdysf3hxv6fmv9ehxet5f9zr5e3hv93njwtxxf3nqd3cvccnzdfhvvmnsdesxyexvdfsvd3rqdpnxsenwdfsx43nxvpevvmxgwpk8q6k2vfnx43kgwp58qckyvt989jrkctdda6kuap6xycrqvp6cqzzsxqrrssrzjqfs8kgq4q0fel6yxesfkxl6de7j9af4g84437k4ceeuquy2h4ut33a03y23dq7ey95qqqqlgqqqqqqgq2qsp56au86fneqmqf97425g3axgdcgd6ew0m92u45qyv9s4qvl2s44t3s9qxpqysgqkzk2e8psallgx37k7elw0lyglgs2px76xcf6fnv58ajq56yxtztr7p8ux8xtr6km254pqv687awm8lx5m3ezjjgx4savjq338wcj2cqqckrdtt",
25
+ "lnbcrt30u1p5ksaf8dqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q22s0qvdeadh5pkey9q0kdedcuy27rad7pahcw0uzksjjp66r5ezwpp5q67767nnt3c4zhpcqyl53rlufrhjqwppknxdyqlzzsxv8gyzmt7ssp5cg3t22jhw3le5lg3njq5has498tjhtr3wm7s0eldn3fu7gyc9nsq9qyysgqcqpcxqrrsslz5wfnkywntd43yjl3efcuz6un4faqkuu3494r4sk3k09kx6t26dpg8y53nfck475rev3z4g33dtfu5xvt2tpgs7qzlgnzngfqzx9j6eu60hp0aws63f395j2uswczfm0kfsz9s3nr8tguqsczug0tfmddu8wcmqxstfwrqr5wd4nvkw6yexa200wezhuyw77jqprt54ga",
26
+ // assetId:
27
+ // "f7ac99f2c068f1157c787012f50cb043437505c309c6d8685e135cd8481b1e9d",
28
+ // invoice:
29
+ // "lnbcrt116692770p1p5k3qd3pp5rklehrt6f4x34qt8hxwy548kg7349paq3k5dnw7jrf0255rgkgpsdysf3hxv6fmv9ehxet5f9zr5e3hv93njwtxxf3nqd3cvccnzdfhvvmnsdesxyexvdfsvd3rqdpnxsenwdfsx43nxvpevvmxgwpk8q6k2vfnx43kgwp58qckyvt989jrkctdda6kuap6xycnydf6cqzzsxqrrssrzjqf7j7xl8rhpycc932pcy382w7f6d664vydks93nuwmtfxh00hft2dap8k2e8ayrtwsqqqqlgqqqqqqgq2qsp5wx26glsp5amuzh8vyl0jkrp7msfqeelwx2cuvxvtysa6my0gq50q9qxpqysgqcq5qg59ckhlrhn5zv49zza0skcqc0yeglthdc7kscz23r54w5zr9yvhnpwklqc6f0933ltr6kjvprnre2armdr5v7kaesgk2vd889ggpqsnepn",
27
30
  });
28
31
  }}
29
32
  >
@@ -33,7 +36,7 @@ createRoot(document.getElementById("root")).render(
33
36
  onClick={() => {
34
37
  astraSend({
35
38
  assetId:
36
- "f7ac99f2c068f1157c787012f50cb043437505c309c6d8685e135cd8481b1e9d",
39
+ "6f9d461d71a18e623c46ceb54aa9602efeab2c137f459c94aec143c9ee5ea29d",
37
40
  amount: 999,
38
41
  });
39
42
  }}
@@ -87,17 +87,122 @@ export const toBytes32 = (value) => {
87
87
 
88
88
  return hash;
89
89
  };
90
+ /**
91
+ * 解析 Lightning Invoice,获取资产信息
92
+ * 使用后端 assetPayReq API 自动识别资产类型(RGB、Taproot Asset 或 BTC)
93
+ * @param {string} payReq - Lightning Invoice 字符串
94
+ * @param {string} assetId - 可选,指定资产 ID。如果不传入,后端会自动识别
95
+ * @returns {Promise<{amount: string, assetId: string, decimal: number}>}
96
+ */
90
97
  export const invoiceToAssetInfo = async ({ payReq, assetId }) => {
91
- const ret = await getAssetPayReq({ payReq: payReq, assetId: assetId });
92
- const { decimal } = ret.data;
93
-
94
- const decodedInvoice = window.lightningPayReq.decode(payReq);
95
- const description = decodedInvoice?.tags.find(
96
- (tag) => tag.tagName === "description"
97
- )?.data;
98
- const extractInfo = extractAssetInfo(description);
99
- return { amount: extractInfo.amount, assetId: assetId, decimal: decimal };
98
+ try {
99
+ // 调用后端 API,后端会自动识别资产类型(RGB/Taproot/BTC)
100
+ const ret = await getAssetPayReq({ payReq: payReq, assetId: assetId });
101
+ const { amount, decimal, asset_id } = ret.data;
102
+
103
+ return {
104
+ amount: amount, // 使用后端返回的精确金额
105
+ assetId: asset_id || assetId, // 优先使用后端返回的 asset_id(支持自动识别)
106
+ decimal: decimal,
107
+ };
108
+ } catch (error) {
109
+ console.error("Failed to parse invoice:", error);
110
+ throw error;
111
+ }
100
112
  };
113
+ /**
114
+ * 校验资产是否在交易对列表中支持
115
+ * @param {string} assetId - 资产 ID(如 BTC、Taproot Asset ID、RGB Asset ID)
116
+ * @param {Array} allAssetPairs - 所有交易对列表
117
+ * @returns {{isSupported: boolean, supportedPairs: Array, error: string|null}}
118
+ */
119
+ export function validateAssetSupport(assetId, allAssetPairs) {
120
+ if (!assetId) {
121
+ return {
122
+ isSupported: false,
123
+ supportedPairs: [],
124
+ error: "Asset ID is required",
125
+ };
126
+ }
127
+
128
+ if (!allAssetPairs || allAssetPairs.length === 0) {
129
+ return {
130
+ isSupported: false,
131
+ supportedPairs: [],
132
+ error: "No trading pairs available. Please wait for pairs to load.",
133
+ };
134
+ }
135
+
136
+ // 查找支持该 asset_id 的交易对
137
+ const supportedPairs = allAssetPairs.filter(
138
+ (pair) => pair?.asset?.assetId === assetId
139
+ );
140
+
141
+ if (supportedPairs.length === 0) {
142
+ const supportedAssetIds = allAssetPairs
143
+ .map((pair) => pair?.asset?.assetId)
144
+ .filter(Boolean);
145
+ return {
146
+ isSupported: false,
147
+ supportedPairs: [],
148
+ error: `Asset "${assetId}" is not supported. Supported assets: ${supportedAssetIds.join(", ")}`,
149
+ };
150
+ }
151
+
152
+ return {
153
+ isSupported: true,
154
+ supportedPairs,
155
+ error: null,
156
+ };
157
+ }
158
+
159
+ /**
160
+ * 校验 token 地址是否在交易对列表中支持
161
+ * @param {string} tokenAddress - Token 合约地址
162
+ * @param {Array} allAssetPairs - 所有交易对列表
163
+ * @returns {{isSupported: boolean, supportedPairs: Array, error: string|null}}
164
+ */
165
+ export function validateTokenSupport(tokenAddress, allAssetPairs) {
166
+ if (!tokenAddress) {
167
+ return {
168
+ isSupported: false,
169
+ supportedPairs: [],
170
+ error: "Token address is required",
171
+ };
172
+ }
173
+
174
+ if (!allAssetPairs || allAssetPairs.length === 0) {
175
+ return {
176
+ isSupported: false,
177
+ supportedPairs: [],
178
+ error: "No trading pairs available. Please wait for pairs to load.",
179
+ };
180
+ }
181
+
182
+ // 查找支持该 token 地址的交易对(不区分大小写)
183
+ const normalizedAddress = tokenAddress.toLowerCase();
184
+ const supportedPairs = allAssetPairs.filter(
185
+ (pair) => pair?.token?.address?.toLowerCase() === normalizedAddress
186
+ );
187
+
188
+ if (supportedPairs.length === 0) {
189
+ const supportedTokens = allAssetPairs
190
+ .map((pair) => pair?.token?.address)
191
+ .filter(Boolean);
192
+ return {
193
+ isSupported: false,
194
+ supportedPairs: [],
195
+ error: `Token "${tokenAddress}" is not supported. Supported tokens: ${supportedTokens.join(", ")}`,
196
+ };
197
+ }
198
+
199
+ return {
200
+ isSupported: true,
201
+ supportedPairs,
202
+ error: null,
203
+ };
204
+ }
205
+
101
206
  export function balanceToFixed(balance, decimals) {
102
207
  const fixedBalance = balance
103
208
  ? new Decimal(balance)
@@ -107,7 +212,21 @@ export function balanceToFixed(balance, decimals) {
107
212
  : 0;
108
213
  return fixedBalance;
109
214
  }
215
+ /**
216
+ * @deprecated 此函数已废弃,建议使用 invoiceToAssetInfo 代替
217
+ * 提取 invoice 中的资产信息(从 memo/description 解析)
218
+ *
219
+ * 废弃原因:
220
+ * 1. 依赖 memo 格式,不够稳定
221
+ * 2. 无法支持 RGB 资产
222
+ * 3. 后端 API 已支持自动识别资产类型,更准确
223
+ *
224
+ * @param {string} inputString - invoice description 字符串
225
+ * @returns {{assetID: string|null, amount: string|null}}
226
+ */
110
227
  export function extractAssetInfo(inputString) {
228
+ console.warn("⚠️ extractAssetInfo is deprecated. Use invoiceToAssetInfo instead.");
229
+
111
230
  const result = {
112
231
  assetID: null,
113
232
  amount: null,