@t402/vue 2.3.1 → 2.5.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 +16 -22
- package/dist/cjs/index.cjs +239 -13
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +302 -2
- package/dist/esm/index.d.ts +302 -2
- package/dist/esm/index.js +237 -14
- package/dist/esm/index.js.map +1 -1
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -12,18 +12,16 @@ npm install @t402/vue
|
|
|
12
12
|
|
|
13
13
|
```vue
|
|
14
14
|
<script setup lang="ts">
|
|
15
|
-
import { PaymentButton, usePaymentRequired } from
|
|
15
|
+
import { PaymentButton, usePaymentRequired } from '@t402/vue'
|
|
16
16
|
|
|
17
|
-
const { paymentRequired, requirements, pay, status } = usePaymentRequired(
|
|
17
|
+
const { paymentRequired, requirements, pay, status } = usePaymentRequired('/api/data')
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<template>
|
|
21
21
|
<div v-if="paymentRequired">
|
|
22
22
|
<PaymentButton :requirements="requirements" :status="status" @pay="pay" />
|
|
23
23
|
</div>
|
|
24
|
-
<div v-else>
|
|
25
|
-
Premium content loaded!
|
|
26
|
-
</div>
|
|
24
|
+
<div v-else>Premium content loaded!</div>
|
|
27
25
|
</template>
|
|
28
26
|
```
|
|
29
27
|
|
|
@@ -34,11 +32,7 @@ const { paymentRequired, requirements, pay, status } = usePaymentRequired("/api/
|
|
|
34
32
|
Renders a payment action button with loading and status states.
|
|
35
33
|
|
|
36
34
|
```vue
|
|
37
|
-
<PaymentButton
|
|
38
|
-
:requirements="requirements"
|
|
39
|
-
:status="status"
|
|
40
|
-
@pay="handlePay"
|
|
41
|
-
/>
|
|
35
|
+
<PaymentButton :requirements="requirements" :status="status" @pay="handlePay" />
|
|
42
36
|
```
|
|
43
37
|
|
|
44
38
|
### PaymentDetails
|
|
@@ -73,11 +67,11 @@ Detects 402 responses and extracts payment requirements.
|
|
|
73
67
|
|
|
74
68
|
```typescript
|
|
75
69
|
const {
|
|
76
|
-
paymentRequired,
|
|
77
|
-
requirements,
|
|
78
|
-
pay,
|
|
79
|
-
status,
|
|
80
|
-
} = usePaymentRequired(url, options)
|
|
70
|
+
paymentRequired, // Ref<boolean>
|
|
71
|
+
requirements, // Ref<PaymentRequirements[]>
|
|
72
|
+
pay, // () => Promise<void>
|
|
73
|
+
status, // Ref<PaymentStatus>
|
|
74
|
+
} = usePaymentRequired(url, options)
|
|
81
75
|
```
|
|
82
76
|
|
|
83
77
|
### usePaymentStatus
|
|
@@ -85,7 +79,7 @@ const {
|
|
|
85
79
|
Tracks the lifecycle of a payment (idle, pending, confirming, complete, error).
|
|
86
80
|
|
|
87
81
|
```typescript
|
|
88
|
-
const { status, error, reset } = usePaymentStatus()
|
|
82
|
+
const { status, error, reset } = usePaymentStatus()
|
|
89
83
|
```
|
|
90
84
|
|
|
91
85
|
### useAsyncPayment
|
|
@@ -93,7 +87,7 @@ const { status, error, reset } = usePaymentStatus();
|
|
|
93
87
|
Manages async payment flows with automatic retry and status tracking.
|
|
94
88
|
|
|
95
89
|
```typescript
|
|
96
|
-
const { execute, status, error } = useAsyncPayment(paymentFn)
|
|
90
|
+
const { execute, status, error } = useAsyncPayment(paymentFn)
|
|
97
91
|
```
|
|
98
92
|
|
|
99
93
|
## Utilities
|
|
@@ -107,15 +101,15 @@ import {
|
|
|
107
101
|
truncateAddress,
|
|
108
102
|
formatTokenAmount,
|
|
109
103
|
choosePaymentRequirement,
|
|
110
|
-
} from
|
|
104
|
+
} from '@t402/vue'
|
|
111
105
|
|
|
112
106
|
// Network detection
|
|
113
|
-
isEvmNetwork(
|
|
107
|
+
isEvmNetwork('eip155:8453') // true
|
|
114
108
|
|
|
115
109
|
// Display helpers
|
|
116
|
-
getNetworkDisplayName(
|
|
117
|
-
truncateAddress(
|
|
118
|
-
formatTokenAmount(1500000n, 6)
|
|
110
|
+
getNetworkDisplayName('eip155:8453') // "Base"
|
|
111
|
+
truncateAddress('0x1234567890abcdef') // "0x1234...cdef"
|
|
112
|
+
formatTokenAmount(1500000n, 6) // "1.50"
|
|
119
113
|
```
|
|
120
114
|
|
|
121
115
|
## Peer Dependencies
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -294,17 +294,17 @@ function getNetworkDisplayName(network) {
|
|
|
294
294
|
return EVM_CHAIN_NAMES[chainId] ?? `Chain ${chainId}`;
|
|
295
295
|
}
|
|
296
296
|
if (network.startsWith("solana:")) {
|
|
297
|
-
const
|
|
298
|
-
return
|
|
297
|
+
const ref9 = network.split(":")[1];
|
|
298
|
+
return ref9 === SOLANA_NETWORK_REFS.DEVNET ? "Solana Devnet" : "Solana";
|
|
299
299
|
}
|
|
300
300
|
if (network.startsWith("ton:")) {
|
|
301
|
-
const
|
|
302
|
-
return
|
|
301
|
+
const ref9 = network.split(":")[1];
|
|
302
|
+
return ref9 === TON_NETWORK_REFS.TESTNET ? "TON Testnet" : "TON";
|
|
303
303
|
}
|
|
304
304
|
if (network.startsWith("tron:")) {
|
|
305
|
-
const
|
|
306
|
-
if (
|
|
307
|
-
if (
|
|
305
|
+
const ref9 = network.split(":")[1];
|
|
306
|
+
if (ref9 === TRON_NETWORK_REFS.NILE) return "TRON Nile";
|
|
307
|
+
if (ref9 === TRON_NETWORK_REFS.SHASTA) return "TRON Shasta";
|
|
308
308
|
return "TRON";
|
|
309
309
|
}
|
|
310
310
|
return network;
|
|
@@ -316,16 +316,16 @@ function isTestnetNetwork(network) {
|
|
|
316
316
|
return TESTNET_CHAIN_IDS.has(chainId);
|
|
317
317
|
}
|
|
318
318
|
if (network.startsWith("solana:")) {
|
|
319
|
-
const
|
|
320
|
-
return
|
|
319
|
+
const ref9 = network.split(":")[1];
|
|
320
|
+
return ref9 === SOLANA_NETWORK_REFS.DEVNET;
|
|
321
321
|
}
|
|
322
322
|
if (network.startsWith("ton:")) {
|
|
323
|
-
const
|
|
324
|
-
return
|
|
323
|
+
const ref9 = network.split(":")[1];
|
|
324
|
+
return ref9 === TON_NETWORK_REFS.TESTNET;
|
|
325
325
|
}
|
|
326
326
|
if (network.startsWith("tron:")) {
|
|
327
|
-
const
|
|
328
|
-
return
|
|
327
|
+
const ref9 = network.split(":")[1];
|
|
328
|
+
return ref9 === TRON_NETWORK_REFS.NILE || ref9 === TRON_NETWORK_REFS.SHASTA;
|
|
329
329
|
}
|
|
330
330
|
return false;
|
|
331
331
|
}
|
|
@@ -716,6 +716,229 @@ function useAsyncPayment(options) {
|
|
|
716
716
|
reset
|
|
717
717
|
};
|
|
718
718
|
}
|
|
719
|
+
function useGaslessPayment(options) {
|
|
720
|
+
const { payFn, onSuccess, onError, autoWait = true } = options;
|
|
721
|
+
const status = vue.ref("idle");
|
|
722
|
+
const userOpHash = vue.ref(null);
|
|
723
|
+
const txHash = vue.ref(null);
|
|
724
|
+
const sponsored = vue.ref(null);
|
|
725
|
+
const error = vue.ref(null);
|
|
726
|
+
const isLoading = vue.computed(() => status.value === "loading");
|
|
727
|
+
const isSuccess = vue.computed(() => status.value === "success");
|
|
728
|
+
const isError = vue.computed(() => status.value === "error");
|
|
729
|
+
const pay = async (params) => {
|
|
730
|
+
status.value = "loading";
|
|
731
|
+
error.value = null;
|
|
732
|
+
userOpHash.value = null;
|
|
733
|
+
txHash.value = null;
|
|
734
|
+
sponsored.value = null;
|
|
735
|
+
try {
|
|
736
|
+
const result = await payFn(params);
|
|
737
|
+
userOpHash.value = result.userOpHash;
|
|
738
|
+
sponsored.value = result.sponsored;
|
|
739
|
+
if (autoWait) {
|
|
740
|
+
const receipt = await result.wait();
|
|
741
|
+
txHash.value = receipt.txHash;
|
|
742
|
+
status.value = "success";
|
|
743
|
+
onSuccess?.(receipt);
|
|
744
|
+
} else {
|
|
745
|
+
status.value = "success";
|
|
746
|
+
onSuccess?.({ txHash: result.userOpHash, success: true });
|
|
747
|
+
}
|
|
748
|
+
} catch (err) {
|
|
749
|
+
const errorMessage = err instanceof Error ? err.message : "Gasless payment failed";
|
|
750
|
+
error.value = errorMessage;
|
|
751
|
+
status.value = "error";
|
|
752
|
+
onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
const reset = () => {
|
|
756
|
+
status.value = "idle";
|
|
757
|
+
userOpHash.value = null;
|
|
758
|
+
txHash.value = null;
|
|
759
|
+
sponsored.value = null;
|
|
760
|
+
error.value = null;
|
|
761
|
+
};
|
|
762
|
+
return {
|
|
763
|
+
pay,
|
|
764
|
+
status,
|
|
765
|
+
userOpHash,
|
|
766
|
+
txHash,
|
|
767
|
+
sponsored,
|
|
768
|
+
error,
|
|
769
|
+
isLoading,
|
|
770
|
+
isSuccess,
|
|
771
|
+
isError,
|
|
772
|
+
reset
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
function useBridgePayment(options) {
|
|
776
|
+
const { bridgeFn, autoBridgeFn, onSuccess, onError, autoWaitForDelivery = false } = options;
|
|
777
|
+
const status = vue.ref("idle");
|
|
778
|
+
const txHash = vue.ref(null);
|
|
779
|
+
const messageGuid = vue.ref(null);
|
|
780
|
+
const dstTxHash = vue.ref(null);
|
|
781
|
+
const error = vue.ref(null);
|
|
782
|
+
const isLoading = vue.computed(
|
|
783
|
+
() => status.value === "bridging" || status.value === "quoting" || status.value === "waiting"
|
|
784
|
+
);
|
|
785
|
+
const isSuccess = vue.computed(() => status.value === "success");
|
|
786
|
+
const isError = vue.computed(() => status.value === "error");
|
|
787
|
+
const executeBridge = async (bridgeCall) => {
|
|
788
|
+
status.value = "bridging";
|
|
789
|
+
error.value = null;
|
|
790
|
+
txHash.value = null;
|
|
791
|
+
messageGuid.value = null;
|
|
792
|
+
dstTxHash.value = null;
|
|
793
|
+
try {
|
|
794
|
+
const result = await bridgeCall();
|
|
795
|
+
txHash.value = result.txHash;
|
|
796
|
+
messageGuid.value = result.messageGuid;
|
|
797
|
+
if (autoWaitForDelivery) {
|
|
798
|
+
status.value = "waiting";
|
|
799
|
+
const delivery = await result.waitForDelivery();
|
|
800
|
+
if (delivery.dstTxHash) dstTxHash.value = delivery.dstTxHash;
|
|
801
|
+
status.value = "success";
|
|
802
|
+
onSuccess?.({
|
|
803
|
+
txHash: result.txHash,
|
|
804
|
+
dstTxHash: delivery.dstTxHash,
|
|
805
|
+
fromChain: result.fromChain,
|
|
806
|
+
toChain: result.toChain
|
|
807
|
+
});
|
|
808
|
+
} else {
|
|
809
|
+
status.value = "success";
|
|
810
|
+
onSuccess?.({
|
|
811
|
+
txHash: result.txHash,
|
|
812
|
+
fromChain: result.fromChain,
|
|
813
|
+
toChain: result.toChain
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
} catch (err) {
|
|
817
|
+
const errorMessage = err instanceof Error ? err.message : "Bridge operation failed";
|
|
818
|
+
error.value = errorMessage;
|
|
819
|
+
status.value = "error";
|
|
820
|
+
onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
const bridge = async (params) => {
|
|
824
|
+
await executeBridge(() => bridgeFn(params));
|
|
825
|
+
};
|
|
826
|
+
const autoBridge = async (params) => {
|
|
827
|
+
const fn = autoBridgeFn ?? (() => {
|
|
828
|
+
throw new Error("autoBridgeFn not provided");
|
|
829
|
+
});
|
|
830
|
+
await executeBridge(() => fn(params));
|
|
831
|
+
};
|
|
832
|
+
const reset = () => {
|
|
833
|
+
status.value = "idle";
|
|
834
|
+
txHash.value = null;
|
|
835
|
+
messageGuid.value = null;
|
|
836
|
+
dstTxHash.value = null;
|
|
837
|
+
error.value = null;
|
|
838
|
+
};
|
|
839
|
+
return {
|
|
840
|
+
bridge,
|
|
841
|
+
autoBridge,
|
|
842
|
+
status,
|
|
843
|
+
txHash,
|
|
844
|
+
messageGuid,
|
|
845
|
+
dstTxHash,
|
|
846
|
+
error,
|
|
847
|
+
isLoading,
|
|
848
|
+
isSuccess,
|
|
849
|
+
isError,
|
|
850
|
+
reset
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function useMultiSigPayment(options) {
|
|
854
|
+
const { initiateFn, submitFn, onSuccess, onError, autoWait = true } = options;
|
|
855
|
+
const status = vue.ref("idle");
|
|
856
|
+
const requestId = vue.ref(null);
|
|
857
|
+
const userOpHash = vue.ref(null);
|
|
858
|
+
const txHash = vue.ref(null);
|
|
859
|
+
const threshold = vue.ref(0);
|
|
860
|
+
const collectedCount = vue.ref(0);
|
|
861
|
+
const isReady = vue.ref(false);
|
|
862
|
+
const error = vue.ref(null);
|
|
863
|
+
const isLoading = vue.computed(() => status.value === "initiating" || status.value === "submitting");
|
|
864
|
+
const isSuccess = vue.computed(() => status.value === "success");
|
|
865
|
+
const isError = vue.computed(() => status.value === "error");
|
|
866
|
+
const initiate = async (params) => {
|
|
867
|
+
status.value = "initiating";
|
|
868
|
+
error.value = null;
|
|
869
|
+
requestId.value = null;
|
|
870
|
+
userOpHash.value = null;
|
|
871
|
+
txHash.value = null;
|
|
872
|
+
try {
|
|
873
|
+
const result = await initiateFn(params);
|
|
874
|
+
requestId.value = result.requestId;
|
|
875
|
+
userOpHash.value = result.userOpHash;
|
|
876
|
+
threshold.value = result.threshold;
|
|
877
|
+
collectedCount.value = result.collectedCount;
|
|
878
|
+
isReady.value = result.isReady;
|
|
879
|
+
status.value = "collecting";
|
|
880
|
+
} catch (err) {
|
|
881
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to initiate multi-sig payment";
|
|
882
|
+
error.value = errorMessage;
|
|
883
|
+
status.value = "error";
|
|
884
|
+
onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
const submit = async () => {
|
|
888
|
+
if (!requestId.value) {
|
|
889
|
+
const err = new Error("No active request to submit");
|
|
890
|
+
error.value = err.message;
|
|
891
|
+
status.value = "error";
|
|
892
|
+
onError?.(err);
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
status.value = "submitting";
|
|
896
|
+
error.value = null;
|
|
897
|
+
try {
|
|
898
|
+
const result = await submitFn(requestId.value);
|
|
899
|
+
if (autoWait) {
|
|
900
|
+
const receipt = await result.wait();
|
|
901
|
+
txHash.value = receipt.txHash;
|
|
902
|
+
status.value = "success";
|
|
903
|
+
onSuccess?.(receipt);
|
|
904
|
+
} else {
|
|
905
|
+
status.value = "success";
|
|
906
|
+
onSuccess?.({ txHash: result.userOpHash, success: true });
|
|
907
|
+
}
|
|
908
|
+
} catch (err) {
|
|
909
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to submit multi-sig transaction";
|
|
910
|
+
error.value = errorMessage;
|
|
911
|
+
status.value = "error";
|
|
912
|
+
onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
const reset = () => {
|
|
916
|
+
status.value = "idle";
|
|
917
|
+
requestId.value = null;
|
|
918
|
+
userOpHash.value = null;
|
|
919
|
+
txHash.value = null;
|
|
920
|
+
threshold.value = 0;
|
|
921
|
+
collectedCount.value = 0;
|
|
922
|
+
isReady.value = false;
|
|
923
|
+
error.value = null;
|
|
924
|
+
};
|
|
925
|
+
return {
|
|
926
|
+
initiate,
|
|
927
|
+
submit,
|
|
928
|
+
status,
|
|
929
|
+
requestId,
|
|
930
|
+
userOpHash,
|
|
931
|
+
txHash,
|
|
932
|
+
threshold,
|
|
933
|
+
collectedCount,
|
|
934
|
+
isReady,
|
|
935
|
+
error,
|
|
936
|
+
isLoading,
|
|
937
|
+
isSuccess,
|
|
938
|
+
isError,
|
|
939
|
+
reset
|
|
940
|
+
};
|
|
941
|
+
}
|
|
719
942
|
|
|
720
943
|
exports.AddressDisplay = AddressDisplay;
|
|
721
944
|
exports.EVM_CHAIN_IDS = EVM_CHAIN_IDS;
|
|
@@ -740,6 +963,9 @@ exports.normalizePaymentRequirements = normalizePaymentRequirements;
|
|
|
740
963
|
exports.spinnerStyles = spinnerStyles;
|
|
741
964
|
exports.truncateAddress = truncateAddress;
|
|
742
965
|
exports.useAsyncPayment = useAsyncPayment;
|
|
966
|
+
exports.useBridgePayment = useBridgePayment;
|
|
967
|
+
exports.useGaslessPayment = useGaslessPayment;
|
|
968
|
+
exports.useMultiSigPayment = useMultiSigPayment;
|
|
743
969
|
exports.usePaymentRequired = usePaymentRequired;
|
|
744
970
|
exports.usePaymentStatus = usePaymentStatus;
|
|
745
971
|
//# sourceMappingURL=index.cjs.map
|