uvd-x402-sdk 2.11.1 → 2.12.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.
Files changed (49) hide show
  1. package/dist/adapters/index.d.mts +1 -1
  2. package/dist/adapters/index.d.ts +1 -1
  3. package/dist/adapters/index.js.map +1 -1
  4. package/dist/adapters/index.mjs.map +1 -1
  5. package/dist/backend/index.d.mts +1 -1
  6. package/dist/backend/index.d.ts +1 -1
  7. package/dist/backend/index.js.map +1 -1
  8. package/dist/backend/index.mjs.map +1 -1
  9. package/dist/{index-C60c_e5z.d.mts → index-C6Vxnneo.d.mts} +1 -1
  10. package/dist/{index-VIOUicmO.d.ts → index-DmJGKD9r.d.ts} +1 -1
  11. package/dist/{index-D-dO_FoP.d.mts → index-fIhvHqCQ.d.mts} +18 -22
  12. package/dist/{index-D-dO_FoP.d.ts → index-fIhvHqCQ.d.ts} +18 -22
  13. package/dist/index.d.mts +2 -2
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/providers/algorand/index.d.mts +11 -5
  18. package/dist/providers/algorand/index.d.ts +11 -5
  19. package/dist/providers/algorand/index.js +97 -27
  20. package/dist/providers/algorand/index.js.map +1 -1
  21. package/dist/providers/algorand/index.mjs +97 -27
  22. package/dist/providers/algorand/index.mjs.map +1 -1
  23. package/dist/providers/evm/index.d.mts +1 -1
  24. package/dist/providers/evm/index.d.ts +1 -1
  25. package/dist/providers/evm/index.js.map +1 -1
  26. package/dist/providers/evm/index.mjs.map +1 -1
  27. package/dist/providers/near/index.d.mts +1 -1
  28. package/dist/providers/near/index.d.ts +1 -1
  29. package/dist/providers/near/index.js.map +1 -1
  30. package/dist/providers/near/index.mjs.map +1 -1
  31. package/dist/providers/solana/index.d.mts +1 -1
  32. package/dist/providers/solana/index.d.ts +1 -1
  33. package/dist/providers/solana/index.js.map +1 -1
  34. package/dist/providers/solana/index.mjs.map +1 -1
  35. package/dist/providers/stellar/index.d.mts +1 -1
  36. package/dist/providers/stellar/index.d.ts +1 -1
  37. package/dist/providers/stellar/index.js.map +1 -1
  38. package/dist/providers/stellar/index.mjs.map +1 -1
  39. package/dist/react/index.d.mts +3 -3
  40. package/dist/react/index.d.ts +3 -3
  41. package/dist/react/index.js.map +1 -1
  42. package/dist/react/index.mjs.map +1 -1
  43. package/dist/utils/index.d.mts +1 -1
  44. package/dist/utils/index.d.ts +1 -1
  45. package/dist/utils/index.js.map +1 -1
  46. package/dist/utils/index.mjs.map +1 -1
  47. package/package.json +1 -1
  48. package/src/providers/algorand/index.ts +117 -32
  49. package/src/types/index.ts +18 -22
@@ -1,4 +1,4 @@
1
- import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Version } from '../../index-D-dO_FoP.mjs';
1
+ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Version } from '../../index-fIhvHqCQ.mjs';
2
2
 
3
3
  /**
4
4
  * uvd-x402-sdk - Algorand Provider
@@ -82,13 +82,19 @@ declare class AlgorandProvider implements WalletAdapter {
82
82
  */
83
83
  getBalance(chainConfig: ChainConfig): Promise<string>;
84
84
  /**
85
- * Create Algorand ASA transfer payment
85
+ * Create Algorand atomic group payment (GoPlausible x402-avm spec)
86
86
  *
87
- * Transaction structure:
88
- * 1. ASA Transfer from user to recipient
89
- * 2. Facilitator pays transaction fees
87
+ * Transaction structure (atomic group):
88
+ * - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees
89
+ * - Transaction 1: ASA transfer (SIGNED) - client -> merchant
90
+ *
91
+ * The facilitator signs transaction 0 and submits the complete atomic group.
90
92
  */
91
93
  signPayment(paymentInfo: PaymentInfo, chainConfig: ChainConfig): Promise<string>;
94
+ /**
95
+ * Decode signed transaction from wallet response (handles various formats)
96
+ */
97
+ private decodeSignedTxn;
92
98
  /**
93
99
  * Encode Algorand payment as X-PAYMENT header
94
100
  *
@@ -1,4 +1,4 @@
1
- import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Version } from '../../index-D-dO_FoP.js';
1
+ import { c as WalletAdapter, C as ChainConfig, P as PaymentInfo, l as X402Version } from '../../index-fIhvHqCQ.js';
2
2
 
3
3
  /**
4
4
  * uvd-x402-sdk - Algorand Provider
@@ -82,13 +82,19 @@ declare class AlgorandProvider implements WalletAdapter {
82
82
  */
83
83
  getBalance(chainConfig: ChainConfig): Promise<string>;
84
84
  /**
85
- * Create Algorand ASA transfer payment
85
+ * Create Algorand atomic group payment (GoPlausible x402-avm spec)
86
86
  *
87
- * Transaction structure:
88
- * 1. ASA Transfer from user to recipient
89
- * 2. Facilitator pays transaction fees
87
+ * Transaction structure (atomic group):
88
+ * - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees
89
+ * - Transaction 1: ASA transfer (SIGNED) - client -> merchant
90
+ *
91
+ * The facilitator signs transaction 0 and submits the complete atomic group.
90
92
  */
91
93
  signPayment(paymentInfo: PaymentInfo, chainConfig: ChainConfig): Promise<string>;
94
+ /**
95
+ * Decode signed transaction from wallet response (handles various formats)
96
+ */
97
+ private decodeSignedTxn;
92
98
  /**
93
99
  * Encode Algorand payment as X-PAYMENT header
94
100
  *
@@ -881,11 +881,13 @@ var AlgorandProvider = class {
881
881
  }
882
882
  }
883
883
  /**
884
- * Create Algorand ASA transfer payment
884
+ * Create Algorand atomic group payment (GoPlausible x402-avm spec)
885
885
  *
886
- * Transaction structure:
887
- * 1. ASA Transfer from user to recipient
888
- * 2. Facilitator pays transaction fees
886
+ * Transaction structure (atomic group):
887
+ * - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees
888
+ * - Transaction 1: ASA transfer (SIGNED) - client -> merchant
889
+ *
890
+ * The facilitator signs transaction 0 and submits the complete atomic group.
889
891
  */
890
892
  async signPayment(paymentInfo, chainConfig) {
891
893
  await loadAlgorandDeps();
@@ -898,40 +900,85 @@ var AlgorandProvider = class {
898
900
  const algodClient = await this.getAlgodClient(chainConfig);
899
901
  const recipient = paymentInfo.recipients?.algorand || paymentInfo.recipient;
900
902
  const assetId = parseInt(chainConfig.usdc.address, 10);
903
+ const facilitatorAddress = paymentInfo.facilitator;
904
+ if (!facilitatorAddress) {
905
+ throw new X402Error(
906
+ "Facilitator address required for Algorand payments. Set paymentInfo.facilitator",
907
+ "PAYMENT_FAILED"
908
+ );
909
+ }
901
910
  const amount = Math.floor(parseFloat(paymentInfo.amount) * 1e6);
902
911
  try {
903
912
  const suggestedParams = await algodClient.getTransactionParams().do();
904
- const txn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
913
+ const feeTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
914
+ sender: facilitatorAddress,
915
+ receiver: facilitatorAddress,
916
+ // self-transfer
917
+ amount: 0,
918
+ suggestedParams: {
919
+ ...suggestedParams,
920
+ fee: 2e3,
921
+ // Covers both transactions (1000 each)
922
+ flatFee: true
923
+ }
924
+ });
925
+ const paymentTxn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
905
926
  sender: this.address,
906
927
  receiver: recipient,
907
928
  amount: BigInt(amount),
908
929
  assetIndex: assetId,
909
- suggestedParams,
930
+ suggestedParams: {
931
+ ...suggestedParams,
932
+ fee: 0,
933
+ // Fee paid by transaction 0
934
+ flatFee: true
935
+ },
910
936
  note: new TextEncoder().encode("x402 payment via uvd-x402-sdk")
911
937
  });
912
- let signedTxn;
938
+ const txnGroup = algosdk.assignGroupID([feeTxn, paymentTxn]);
939
+ const unsignedFeeTxnBytes = algosdk.encodeUnsignedTransaction(txnGroup[0]);
940
+ const unsignedFeeTxnBase64 = uint8ArrayToBase64(unsignedFeeTxnBytes);
941
+ let signedPaymentTxnBytes;
913
942
  if (this.walletType === "lute" && this.luteWallet) {
914
- const txnBase64 = uint8ArrayToBase64(txn.toByte());
915
- const signedTxns = await this.luteWallet.signTxns([{ txn: txnBase64 }]);
916
- if (!signedTxns || signedTxns.length === 0 || !signedTxns[0]) {
943
+ const feeTxnBase64 = uint8ArrayToBase64(txnGroup[0].toByte());
944
+ const paymentTxnBase64 = uint8ArrayToBase64(txnGroup[1].toByte());
945
+ const signedTxns = await this.luteWallet.signTxns([
946
+ { txn: feeTxnBase64, signers: [] },
947
+ // Don't sign - facilitator will
948
+ { txn: paymentTxnBase64 }
949
+ // Sign this one
950
+ ]);
951
+ if (!signedTxns || signedTxns.length < 2 || !signedTxns[1]) {
917
952
  throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
918
953
  }
919
- signedTxn = Uint8Array.from(atob(signedTxns[0]), (c) => c.charCodeAt(0));
954
+ const signedResult = signedTxns[1];
955
+ signedPaymentTxnBytes = this.decodeSignedTxn(signedResult);
920
956
  } else if (this.walletType === "pera" && this.peraWallet) {
921
- const signedTxns = await this.peraWallet.signTransaction([[{ txn }]]);
922
- if (!signedTxns || signedTxns.length === 0) {
957
+ const signedTxns = await this.peraWallet.signTransaction([
958
+ [
959
+ { txn: txnGroup[0], signers: [] },
960
+ // Don't sign - facilitator will
961
+ { txn: txnGroup[1] }
962
+ // Sign this one
963
+ ]
964
+ ]);
965
+ if (!signedTxns || signedTxns.length < 2 || !signedTxns[1]) {
923
966
  throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
924
967
  }
925
- signedTxn = signedTxns[0];
968
+ signedPaymentTxnBytes = signedTxns[1];
926
969
  } else {
927
970
  throw new X402Error("No wallet available for signing", "WALLET_NOT_CONNECTED");
928
971
  }
972
+ const signedPaymentTxnBase64 = uint8ArrayToBase64(signedPaymentTxnBytes);
929
973
  const payload = {
930
- from: this.address,
931
- to: recipient,
932
- amount: amount.toString(),
933
- assetId,
934
- signedTxn: uint8ArrayToBase64(signedTxn)
974
+ paymentIndex: 1,
975
+ // Index of the payment transaction in the group
976
+ paymentGroup: [
977
+ unsignedFeeTxnBase64,
978
+ // Transaction 0: unsigned fee tx
979
+ signedPaymentTxnBase64
980
+ // Transaction 1: signed payment tx
981
+ ]
935
982
  };
936
983
  return JSON.stringify(payload);
937
984
  } catch (error) {
@@ -950,6 +997,29 @@ var AlgorandProvider = class {
950
997
  );
951
998
  }
952
999
  }
1000
+ /**
1001
+ * Decode signed transaction from wallet response (handles various formats)
1002
+ */
1003
+ decodeSignedTxn(signedResult) {
1004
+ if (signedResult instanceof Uint8Array) {
1005
+ return signedResult;
1006
+ } else if (typeof signedResult === "string") {
1007
+ try {
1008
+ return Uint8Array.from(atob(signedResult), (c) => c.charCodeAt(0));
1009
+ } catch {
1010
+ const standardBase64 = signedResult.replace(/-/g, "+").replace(/_/g, "/");
1011
+ return Uint8Array.from(atob(standardBase64), (c) => c.charCodeAt(0));
1012
+ }
1013
+ } else if (ArrayBuffer.isView(signedResult)) {
1014
+ return new Uint8Array(
1015
+ signedResult.buffer,
1016
+ signedResult.byteOffset,
1017
+ signedResult.byteLength
1018
+ );
1019
+ } else {
1020
+ throw new X402Error("Unexpected signed transaction format", "PAYMENT_FAILED");
1021
+ }
1022
+ }
953
1023
  /**
954
1024
  * Encode Algorand payment as X-PAYMENT header
955
1025
  *
@@ -960,14 +1030,15 @@ var AlgorandProvider = class {
960
1030
  */
961
1031
  encodePaymentHeader(paymentPayload, chainConfig, version = 1) {
962
1032
  const payload = JSON.parse(paymentPayload);
963
- const networkName = chainConfig?.name || "algorand";
1033
+ let networkName;
1034
+ if (chainConfig?.name === "algorand-testnet") {
1035
+ networkName = "algorand-testnet";
1036
+ } else {
1037
+ networkName = "algorand-mainnet";
1038
+ }
964
1039
  const payloadData = {
965
- from: payload.from,
966
- to: payload.to,
967
- amount: payload.amount,
968
- assetId: payload.assetId,
969
- signedTxn: payload.signedTxn,
970
- ...payload.note && { note: payload.note }
1040
+ paymentIndex: payload.paymentIndex,
1041
+ paymentGroup: payload.paymentGroup
971
1042
  };
972
1043
  const x402Payload = version === 2 ? {
973
1044
  x402Version: 2,
@@ -979,7 +1050,6 @@ var AlgorandProvider = class {
979
1050
  x402Version: 1,
980
1051
  scheme: "exact",
981
1052
  network: networkName,
982
- // Plain chain name for v1
983
1053
  payload: payloadData
984
1054
  };
985
1055
  return btoa(JSON.stringify(x402Payload));