@zebec-network/exchange-card-sdk 1.1.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +339 -0
  3. package/dist/artifacts/abi/ERC20.json +350 -0
  4. package/dist/artifacts/abi/ZebecCard.json +1060 -0
  5. package/dist/artifacts/abi/index.d.ts +122 -0
  6. package/dist/artifacts/abi/index.js +10 -0
  7. package/dist/artifacts/index.d.ts +2 -0
  8. package/dist/artifacts/index.js +18 -0
  9. package/dist/artifacts/typechain-types/ERC20.d.ts +149 -0
  10. package/dist/artifacts/typechain-types/ERC20.js +2 -0
  11. package/dist/artifacts/typechain-types/ZebecCard.d.ts +639 -0
  12. package/dist/artifacts/typechain-types/ZebecCard.js +2 -0
  13. package/dist/artifacts/typechain-types/common.d.ts +50 -0
  14. package/dist/artifacts/typechain-types/common.js +2 -0
  15. package/dist/artifacts/typechain-types/factories/ERC20__factory.d.ts +280 -0
  16. package/dist/artifacts/typechain-types/factories/ERC20__factory.js +378 -0
  17. package/dist/artifacts/typechain-types/factories/ZebecCard__factory.d.ts +835 -0
  18. package/dist/artifacts/typechain-types/factories/ZebecCard__factory.js +1088 -0
  19. package/dist/artifacts/typechain-types/factories/index.d.ts +2 -0
  20. package/dist/artifacts/typechain-types/factories/index.js +10 -0
  21. package/dist/artifacts/typechain-types/index.d.ts +5 -0
  22. package/dist/artifacts/typechain-types/index.js +31 -0
  23. package/dist/chains.d.ts +18 -0
  24. package/dist/chains.js +39 -0
  25. package/dist/constants.d.ts +3649 -0
  26. package/dist/constants.js +2502 -0
  27. package/dist/errors.d.ts +24 -0
  28. package/dist/errors.js +51 -0
  29. package/dist/helpers/apiHelpers.d.ts +30 -0
  30. package/dist/helpers/apiHelpers.js +92 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.js +26 -0
  33. package/dist/services/EvmService.d.ts +37 -0
  34. package/dist/services/EvmService.js +134 -0
  35. package/dist/services/TaoService.d.ts +49 -0
  36. package/dist/services/TaoService.js +106 -0
  37. package/dist/services/TonService.d.ts +57 -0
  38. package/dist/services/TonService.js +137 -0
  39. package/dist/services/XdbService.d.ts +58 -0
  40. package/dist/services/XdbService.js +140 -0
  41. package/dist/services/stellarService.d.ts +52 -0
  42. package/dist/services/stellarService.js +119 -0
  43. package/dist/types.d.ts +59 -0
  44. package/dist/types.js +263 -0
  45. package/dist/utils.d.ts +8 -0
  46. package/dist/utils.js +48 -0
  47. package/package.json +58 -0
@@ -0,0 +1,24 @@
1
+ export declare class UnsupportedChainError extends Error {
2
+ name: string;
3
+ constructor(chainId: number);
4
+ }
5
+ export declare class InvalidEmailError extends Error {
6
+ name: string;
7
+ constructor(email: string);
8
+ }
9
+ export declare class NotEnoughBalanceError extends Error {
10
+ name: string;
11
+ constructor(currentBalance: string, requiredBalance: string);
12
+ }
13
+ export declare class CardPurchaseAmountOutOfRangeError extends Error {
14
+ name: string;
15
+ constructor(minRange: string, maxRange: string);
16
+ }
17
+ export declare class DailyCardPurchaseLimitExceedError extends Error {
18
+ name: string;
19
+ constructor(dailyLimit: string, purchaseOfADay: string);
20
+ }
21
+ export declare class ValidationError extends Error {
22
+ name: string;
23
+ constructor(message: string);
24
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationError = exports.DailyCardPurchaseLimitExceedError = exports.CardPurchaseAmountOutOfRangeError = exports.NotEnoughBalanceError = exports.InvalidEmailError = exports.UnsupportedChainError = void 0;
4
+ class UnsupportedChainError extends Error {
5
+ name = "UnsupportedChainError";
6
+ constructor(chainId) {
7
+ super("Unsupported chainId: " + chainId);
8
+ }
9
+ }
10
+ exports.UnsupportedChainError = UnsupportedChainError;
11
+ class InvalidEmailError extends Error {
12
+ name = "InvalidEmailError";
13
+ constructor(email) {
14
+ super("Invalid email: " + email);
15
+ }
16
+ }
17
+ exports.InvalidEmailError = InvalidEmailError;
18
+ class NotEnoughBalanceError extends Error {
19
+ name = "NotEnoughBalanceError";
20
+ constructor(currentBalance, requiredBalance) {
21
+ super("Not enough balance. Current amount: " +
22
+ currentBalance +
23
+ " Required amount: " +
24
+ requiredBalance);
25
+ }
26
+ }
27
+ exports.NotEnoughBalanceError = NotEnoughBalanceError;
28
+ class CardPurchaseAmountOutOfRangeError extends Error {
29
+ name = "BuyAmountOutOfRangeError";
30
+ constructor(minRange, maxRange) {
31
+ super("Amount must be with range: " + minRange + " - " + maxRange);
32
+ }
33
+ }
34
+ exports.CardPurchaseAmountOutOfRangeError = CardPurchaseAmountOutOfRangeError;
35
+ class DailyCardPurchaseLimitExceedError extends Error {
36
+ name = "DailyCardPurchaseLimitExceedError";
37
+ constructor(dailyLimit, purchaseOfADay) {
38
+ super("Requested card purchase amount exceeds daily purchase limit. Daily limit: " +
39
+ dailyLimit +
40
+ " Today's purchase amount: " +
41
+ purchaseOfADay);
42
+ }
43
+ }
44
+ exports.DailyCardPurchaseLimitExceedError = DailyCardPurchaseLimitExceedError;
45
+ class ValidationError extends Error {
46
+ name = "ValidationError";
47
+ constructor(message) {
48
+ super(message);
49
+ }
50
+ }
51
+ exports.ValidationError = ValidationError;
@@ -0,0 +1,30 @@
1
+ import { Quote } from "../types";
2
+ export type APIConfig = {
3
+ apiKey: string;
4
+ encryptionKey: string;
5
+ };
6
+ export declare class ZebecCardAPIService {
7
+ readonly apiConfig: APIConfig & {
8
+ apiUrl: string;
9
+ };
10
+ private readonly sdkVersion;
11
+ private readonly api;
12
+ constructor(apiConfig: APIConfig, sandbox?: boolean);
13
+ private generateSignature;
14
+ generateRequestHeaders(method: string, path: string, body?: any): {
15
+ "X-API-Key": string;
16
+ "X-Timestamp": string;
17
+ "X-Nonce": string;
18
+ "X-Signature": string;
19
+ "X-SDK-Version": string;
20
+ "Content-Type": string;
21
+ };
22
+ encryptSensitiveData(data: any): string;
23
+ ping(): Promise<boolean>;
24
+ purchaseCard(data: any): Promise<import("axios").AxiosResponse<any, any>>;
25
+ fetchQuote(symbol: string): Promise<Quote>;
26
+ fetchVault(symbol: string): Promise<{
27
+ depositVault: string;
28
+ tag?: string;
29
+ }>;
30
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ZebecCardAPIService = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const constants_1 = require("../constants");
10
+ class ZebecCardAPIService {
11
+ apiConfig;
12
+ sdkVersion = "1.0.0";
13
+ api;
14
+ constructor(apiConfig, sandbox) {
15
+ this.apiConfig = {
16
+ ...apiConfig,
17
+ apiUrl: sandbox ? constants_1.CARD_API_URL.Sandbox : constants_1.CARD_API_URL.Production,
18
+ };
19
+ this.api = axios_1.default.create({ baseURL: this.apiConfig.apiUrl });
20
+ }
21
+ // Generate request signature
22
+ generateSignature(method, path, timestamp, body) {
23
+ const stringToSign = [
24
+ method.toUpperCase(),
25
+ path,
26
+ timestamp,
27
+ this.apiConfig.apiKey,
28
+ body ? JSON.stringify(body) : "",
29
+ ].join("");
30
+ return crypto_1.default
31
+ .createHmac("sha256", this.apiConfig.encryptionKey)
32
+ .update(stringToSign)
33
+ .digest("hex");
34
+ }
35
+ // Generate request headers
36
+ generateRequestHeaders(method, path, body) {
37
+ const timestamp = Math.floor(Date.now() / 1000);
38
+ const nonce = crypto_1.default.randomBytes(16).toString("hex");
39
+ return {
40
+ "X-API-Key": this.apiConfig.apiKey,
41
+ "X-Timestamp": timestamp.toString(),
42
+ "X-Nonce": nonce,
43
+ "X-Signature": this.generateSignature(method, path, timestamp, body),
44
+ "X-SDK-Version": this.sdkVersion,
45
+ "Content-Type": "application/json",
46
+ };
47
+ }
48
+ // Encrypt sensitive data fields
49
+ encryptSensitiveData(data) {
50
+ const iv = crypto_1.default.randomBytes(16);
51
+ const key = crypto_1.default.pbkdf2Sync(this.apiConfig.encryptionKey, iv, 1000, 32, "sha256");
52
+ const cipher = crypto_1.default.createCipheriv("aes-256-gcm", key, iv);
53
+ let encrypted = cipher.update(JSON.stringify(data), "utf8", "base64");
54
+ encrypted += cipher.final("base64");
55
+ const authTag = cipher.getAuthTag();
56
+ return `${iv.toString("base64")}:${encrypted}:${authTag.toString("base64")}`;
57
+ }
58
+ // Ping API status
59
+ async ping() {
60
+ try {
61
+ await this.api.get("/ping");
62
+ return true;
63
+ }
64
+ catch (error) {
65
+ throw new Error("Card service is down. Please try again later.");
66
+ }
67
+ }
68
+ // Purchase Card
69
+ async purchaseCard(data) {
70
+ console.debug("Payload data:", data);
71
+ const encryptedData = this.encryptSensitiveData(data);
72
+ console.debug("Encrypted Data: %s \n", encryptedData);
73
+ const method = "POST";
74
+ const path = "/orders/create";
75
+ const url = this.apiConfig.apiUrl + path;
76
+ const payload = { data: encryptedData };
77
+ const headers = this.generateRequestHeaders(method, path, payload);
78
+ const response = await axios_1.default.post(url, payload, { headers });
79
+ return response;
80
+ }
81
+ // Fetch quote
82
+ async fetchQuote(symbol) {
83
+ const response = await this.api.get("/exchange/price", { params: { symbol } });
84
+ const data = response.data;
85
+ return data;
86
+ }
87
+ async fetchVault(symbol) {
88
+ const { data } = await this.api.get(`/exchange/deposit-address`, { params: { symbol } });
89
+ return data;
90
+ }
91
+ }
92
+ exports.ZebecCardAPIService = ZebecCardAPIService;
@@ -0,0 +1,10 @@
1
+ export * from "./artifacts";
2
+ export * from "./chains";
3
+ export * from "./constants";
4
+ export * from "./errors";
5
+ export * from "./services/EvmService";
6
+ export * from "./services/TaoService";
7
+ export * from "./services/TonService";
8
+ export * from "./services/stellarService";
9
+ export * from "./types";
10
+ export * from "./utils";
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./artifacts"), exports);
18
+ __exportStar(require("./chains"), exports);
19
+ __exportStar(require("./constants"), exports);
20
+ __exportStar(require("./errors"), exports);
21
+ __exportStar(require("./services/EvmService"), exports);
22
+ __exportStar(require("./services/TaoService"), exports);
23
+ __exportStar(require("./services/TonService"), exports);
24
+ __exportStar(require("./services/stellarService"), exports);
25
+ __exportStar(require("./types"), exports);
26
+ __exportStar(require("./utils"), exports);
@@ -0,0 +1,37 @@
1
+ import { AxiosResponse } from "axios";
2
+ import { ethers } from "ethers";
3
+ import { ERC20, ZebecCard } from "../artifacts";
4
+ import { SupportedChain } from "../chains";
5
+ import { Quote, Recipient } from "../types";
6
+ import { APIConfig } from "../helpers/apiHelpers";
7
+ export declare class ZebecCardService {
8
+ readonly signer: ethers.Signer;
9
+ readonly zebecCard: ZebecCard;
10
+ readonly usdcToken: ERC20;
11
+ readonly chainId: SupportedChain;
12
+ private readonly apiService;
13
+ constructor(signer: ethers.Signer, chainId: number, apiConfig: APIConfig, sdkOptions?: {
14
+ sandbox?: boolean;
15
+ });
16
+ /**
17
+ * Fetches a quote for the given amount.
18
+ *
19
+ * @param {string | number} amount - The amount for which to fetch the quote.
20
+ * @returns {Promise<Quote>} A promise that resolves to a Quote object.
21
+ */
22
+ fetchQuote(): Promise<Quote>;
23
+ /**
24
+ * Transfer specified amount from user's vault balance to card vault with some fee amount for card purchase.
25
+ * @param params
26
+ * @returns
27
+ */
28
+ purchaseCard(params: {
29
+ amount: number;
30
+ recipient: Recipient;
31
+ quote: Quote;
32
+ }): Promise<[
33
+ ethers.ContractTransactionResponse,
34
+ ethers.ContractTransactionResponse,
35
+ AxiosResponse
36
+ ]>;
37
+ }
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZebecCardService = void 0;
4
+ const axios_1 = require("axios");
5
+ const ethers_1 = require("ethers");
6
+ const artifacts_1 = require("../artifacts");
7
+ const chains_1 = require("../chains");
8
+ const constants_1 = require("../constants");
9
+ const errors_1 = require("../errors");
10
+ const types_1 = require("../types");
11
+ const utils_1 = require("../utils");
12
+ const apiHelpers_1 = require("../helpers/apiHelpers");
13
+ class ZebecCardService {
14
+ signer;
15
+ zebecCard;
16
+ usdcToken;
17
+ chainId;
18
+ apiService;
19
+ constructor(signer, chainId, apiConfig, sdkOptions) {
20
+ this.signer = signer;
21
+ const sandbox = sdkOptions?.sandbox ? sdkOptions.sandbox : false;
22
+ const isTesnetChainId = chains_1.TESTNET_CHAINIDS.includes(chainId);
23
+ if ((sandbox && !isTesnetChainId) || (!sandbox && isTesnetChainId)) {
24
+ throw new Error("Only testnet chains are allowed in sandbox environment");
25
+ }
26
+ this.apiService = new apiHelpers_1.ZebecCardAPIService(apiConfig, sandbox);
27
+ this.chainId = (0, chains_1.parseSupportedChain)(chainId);
28
+ const zebecCardAddress = constants_1.ZEBEC_CARD_ADDRESS[this.chainId];
29
+ const usdcAddress = constants_1.USDC_ADDRESS[this.chainId];
30
+ this.zebecCard = artifacts_1.ZebecCard__factory.connect(zebecCardAddress, signer);
31
+ this.usdcToken = artifacts_1.ERC20__factory.connect(usdcAddress, signer);
32
+ }
33
+ /**
34
+ * Fetches a quote for the given amount.
35
+ *
36
+ * @param {string | number} amount - The amount for which to fetch the quote.
37
+ * @returns {Promise<Quote>} A promise that resolves to a Quote object.
38
+ */
39
+ async fetchQuote() {
40
+ const res = await this.apiService.fetchQuote("USDC");
41
+ return res;
42
+ }
43
+ /**
44
+ * Transfer specified amount from user's vault balance to card vault with some fee amount for card purchase.
45
+ * @param params
46
+ * @returns
47
+ */
48
+ async purchaseCard(params) {
49
+ // Check card service status
50
+ await this.apiService.ping();
51
+ const decimals = await this.usdcToken.decimals();
52
+ const totalAmount = (0, utils_1.formatAmount)(params.amount + constants_1.PLATFORM_FEE, Number(decimals));
53
+ const parsedAmount = ethers_1.ethers.parseUnits(totalAmount.toString(), decimals);
54
+ if (!(0, utils_1.isEmailValid)(params.recipient.emailAddress)) {
55
+ throw new errors_1.InvalidEmailError(params.recipient.emailAddress);
56
+ }
57
+ const usdcBalance = await this.usdcToken.balanceOf(this.signer);
58
+ console.debug("Usdc Balance:", usdcBalance);
59
+ if (parsedAmount > usdcBalance) {
60
+ throw new errors_1.NotEnoughBalanceError(ethers_1.ethers.formatUnits(usdcBalance, decimals), params.amount.toString());
61
+ }
62
+ let cardConfig = await this.zebecCard.cardConfig();
63
+ const minRange = cardConfig.minCardAmount;
64
+ const maxRange = cardConfig.maxCardAmount;
65
+ if (parsedAmount < minRange || parsedAmount > maxRange) {
66
+ throw new errors_1.CardPurchaseAmountOutOfRangeError(ethers_1.ethers.formatUnits(minRange, decimals), ethers_1.ethers.formatUnits(maxRange, decimals));
67
+ }
68
+ const cardPurchaseInfo = await this.zebecCard.cardPurchases(this.signer);
69
+ const lastCardPurchaseDate = new Date(Number(cardPurchaseInfo.unixInRecord * 1000n));
70
+ const today = new Date();
71
+ let cardPurchaseOfDay = 0n;
72
+ if ((0, utils_1.areDatesOfSameDay)(today, lastCardPurchaseDate)) {
73
+ cardPurchaseOfDay = cardPurchaseInfo.totalCardBoughtPerDay + parsedAmount;
74
+ }
75
+ else {
76
+ cardPurchaseOfDay = parsedAmount;
77
+ }
78
+ if (cardPurchaseOfDay > cardConfig.dailyCardBuyLimit) {
79
+ throw new errors_1.DailyCardPurchaseLimitExceedError(ethers_1.ethers.formatUnits(cardConfig.dailyCardBuyLimit, decimals), ethers_1.ethers.formatUnits(cardPurchaseInfo.totalCardBoughtPerDay, decimals));
80
+ }
81
+ const allowance = await this.usdcToken.allowance(this.signer, this.zebecCard);
82
+ console.debug("Allowance:", allowance);
83
+ if (allowance < parsedAmount) {
84
+ console.debug("===== Approving token =====");
85
+ const approveResponse = await this.usdcToken.approve(this.zebecCard, parsedAmount);
86
+ const approveReceipt = await approveResponse.wait();
87
+ console.debug("Approve hash: %s \n", approveReceipt?.hash);
88
+ }
89
+ console.debug("===== Depositing USDC =====");
90
+ const depositResponse = await this.zebecCard.depositUsdc(parsedAmount);
91
+ const depositReceipt = await depositResponse.wait();
92
+ console.debug("Deposit hash: %s \n", depositReceipt?.hash);
93
+ cardConfig = await this.zebecCard.cardConfig();
94
+ const purchaseCounter = Number((cardConfig.counter + 1n).toString());
95
+ const cardTypeId = "103253238082";
96
+ const emailHash = await (0, utils_1.hashSHA256)(params.recipient.emailAddress);
97
+ console.debug("===== Purchasing Card =====");
98
+ const buyCardResponse = await this.zebecCard.buyCard(parsedAmount, cardTypeId, emailHash);
99
+ const buyCardReceipt = await buyCardResponse.wait();
100
+ console.debug("Purchase hash: %s \n", buyCardReceipt?.hash);
101
+ const usdAmount = types_1.Money.USD(params.amount);
102
+ const buyer = await this.signer.getAddress();
103
+ const receipt = new types_1.Receipt(params.quote, new types_1.Deposit("USDC", Number(totalAmount), "", buyer, buyCardResponse.hash, "", this.chainId, purchaseCounter));
104
+ const payload = new types_1.OrderCardRequest(usdAmount, params.recipient, receipt);
105
+ let retries = 0;
106
+ let delay = 1000; // Initial delay in milliseconds (1 second)
107
+ const maxRetries = 5; // Max retry default
108
+ while (retries < maxRetries) {
109
+ try {
110
+ const response = await this.apiService.purchaseCard(payload);
111
+ console.debug("API response: %o \n", response.data);
112
+ return [depositResponse, buyCardResponse, response];
113
+ }
114
+ catch (error) {
115
+ if (error instanceof axios_1.AxiosError) {
116
+ console.debug("error", error.response?.data);
117
+ console.debug("error", error.message);
118
+ }
119
+ else {
120
+ console.debug("error", error);
121
+ }
122
+ if (retries >= maxRetries) {
123
+ throw error;
124
+ }
125
+ retries += 1;
126
+ console.debug(`Retrying in ${delay / 1000} seconds...`);
127
+ await new Promise((resolve) => setTimeout(resolve, delay));
128
+ delay *= 2; // Exponential backoff
129
+ }
130
+ }
131
+ throw new Error("Max retries reached");
132
+ }
133
+ }
134
+ exports.ZebecCardService = ZebecCardService;
@@ -0,0 +1,49 @@
1
+ import { Quote } from "../types";
2
+ import { Signer } from "@polkadot/types/types";
3
+ import { KeyringPair } from "@polkadot/keyring/types";
4
+ import { APIConfig } from "../helpers/apiHelpers";
5
+ export declare class ZebecCardTAOService {
6
+ readonly signer: Signer | KeyringPair;
7
+ private apiService;
8
+ private taoRPC;
9
+ /**
10
+ * Constructs an instance of the service.
11
+ *
12
+ * @param {Signer} signer - The signer which can be either a PolkadotJs Signer or a KeyringPair.
13
+ * @param {APIConfig} apiConfig - The configuration object for the API.
14
+ * @param sdkOptions - Optional configuration for the SDK.
15
+ */
16
+ constructor(signer: Signer | KeyringPair, apiConfig: APIConfig, sdkOptions?: {
17
+ sandbox?: boolean;
18
+ });
19
+ /**
20
+ * Fetches a quote for the given amount.
21
+ *
22
+ * @param {string | number} amount - The amount for which to fetch the quote.
23
+ * @returns {Promise<Quote>} A promise that resolves to a Quote object.
24
+ */
25
+ fetchQuote(): Promise<Quote>;
26
+ /**
27
+ * Fetches the TAO Vault address.
28
+ *
29
+ * @returns {Promise<string>} A promise that resolves to the TAO Vault address.
30
+ */
31
+ fetchTAOVault(): Promise<string>;
32
+ /**
33
+ * Executes TAO token transfer for card purchase.
34
+ *
35
+ * @param params - The parameters required for token transfer.
36
+ * @param params.walletAddress - The wallet address from which TAO tokens will be transferred.
37
+ * @param params.amount - The amount of TAO tokens to transfer.
38
+ * @param params.depositAddress - The destination address to receive tokens.
39
+ * @returns A promise that resolves to an object containing transaction and block hashes.
40
+ * @throws {Error} If there is not enough balance or if the transaction fails.
41
+ */
42
+ transferTAO(params: {
43
+ walletAddress: string;
44
+ amount: number;
45
+ }): Promise<{
46
+ txHash: string;
47
+ blockHash: string;
48
+ }>;
49
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZebecCardTAOService = void 0;
4
+ const constants_1 = require("../constants");
5
+ const api_1 = require("@polkadot/api");
6
+ const api_2 = require("@polkadot/api");
7
+ const apiHelpers_1 = require("../helpers/apiHelpers");
8
+ class ZebecCardTAOService {
9
+ signer;
10
+ apiService;
11
+ taoRPC;
12
+ /**
13
+ * Constructs an instance of the service.
14
+ *
15
+ * @param {Signer} signer - The signer which can be either a PolkadotJs Signer or a KeyringPair.
16
+ * @param {APIConfig} apiConfig - The configuration object for the API.
17
+ * @param sdkOptions - Optional configuration for the SDK.
18
+ */
19
+ constructor(signer, apiConfig, sdkOptions) {
20
+ this.signer = signer;
21
+ const sandbox = sdkOptions?.sandbox ? sdkOptions.sandbox : false;
22
+ this.apiService = new apiHelpers_1.ZebecCardAPIService(apiConfig, sandbox);
23
+ this.taoRPC = sandbox ? constants_1.TAO_RPC_URL.Sandbox : constants_1.TAO_RPC_URL.Production;
24
+ }
25
+ /**
26
+ * Fetches a quote for the given amount.
27
+ *
28
+ * @param {string | number} amount - The amount for which to fetch the quote.
29
+ * @returns {Promise<Quote>} A promise that resolves to a Quote object.
30
+ */
31
+ async fetchQuote() {
32
+ const res = await this.apiService.fetchQuote("TAO");
33
+ return res;
34
+ }
35
+ /**
36
+ * Fetches the TAO Vault address.
37
+ *
38
+ * @returns {Promise<string>} A promise that resolves to the TAO Vault address.
39
+ */
40
+ async fetchTAOVault() {
41
+ const data = await this.apiService.fetchVault("TAO");
42
+ return data.depositVault;
43
+ }
44
+ /**
45
+ * Executes TAO token transfer for card purchase.
46
+ *
47
+ * @param params - The parameters required for token transfer.
48
+ * @param params.walletAddress - The wallet address from which TAO tokens will be transferred.
49
+ * @param params.amount - The amount of TAO tokens to transfer.
50
+ * @param params.depositAddress - The destination address to receive tokens.
51
+ * @returns A promise that resolves to an object containing transaction and block hashes.
52
+ * @throws {Error} If there is not enough balance or if the transaction fails.
53
+ */
54
+ async transferTAO(params) {
55
+ // Connect to TAO network
56
+ const provider = new api_1.WsProvider(this.taoRPC);
57
+ const api = await api_2.ApiPromise.create({ provider });
58
+ try {
59
+ // Calculate total amount with proper decimal places
60
+ const totalAmount = Math.floor(params.amount * 10 ** 9);
61
+ // Check wallet balance
62
+ const balance = await api?.query.system.account(params.walletAddress);
63
+ const freeBalance = balance.data.free.toNumber();
64
+ if (freeBalance < totalAmount) {
65
+ throw new Error("Not enough balance");
66
+ }
67
+ // Create and submit transaction
68
+ let resolveOut;
69
+ let rejectOut;
70
+ const promise = new Promise((resolve, reject) => {
71
+ resolveOut = resolve;
72
+ rejectOut = reject;
73
+ });
74
+ let blockHash = "";
75
+ let txHash = "";
76
+ const depositAddress = await this.fetchTAOVault();
77
+ const tx = api.tx.balances.transferKeepAlive(depositAddress, totalAmount);
78
+ const unsub = await tx.signAndSend("address" in this.signer ? this.signer : params.walletAddress, {
79
+ signer: "address" in this.signer ? undefined : this.signer,
80
+ }, ({ events = [], isInBlock, isFinalized, isError, status, txHash: _txHash }) => {
81
+ console.debug("Transaction status:", status.type);
82
+ if (isInBlock || isFinalized) {
83
+ console.debug("Included at block hash", status.asInBlock.toHex());
84
+ blockHash = status.asInBlock.toHex();
85
+ txHash = _txHash.toHex();
86
+ const isSuccess = events.every(({ event }) => !api.events.system.ExtrinsicFailed.is(event));
87
+ if (isSuccess) {
88
+ unsub();
89
+ resolveOut();
90
+ }
91
+ }
92
+ else if (isError) {
93
+ unsub();
94
+ rejectOut(new Error("Transaction failed"));
95
+ }
96
+ });
97
+ await promise;
98
+ return { txHash, blockHash };
99
+ }
100
+ finally {
101
+ // Ensure API is disconnected
102
+ await api.disconnect().catch(() => { });
103
+ }
104
+ }
105
+ }
106
+ exports.ZebecCardTAOService = ZebecCardTAOService;
@@ -0,0 +1,57 @@
1
+ import { APIConfig } from "../helpers/apiHelpers";
2
+ import { ITonConnect } from "@tonconnect/sdk";
3
+ import { Quote } from "../types";
4
+ export declare class ZebecCardTONService {
5
+ readonly signer: ITonConnect;
6
+ private apiService;
7
+ private tonRPC;
8
+ private tonweb;
9
+ private sandbox;
10
+ /**
11
+ * Constructs an instance of the service.
12
+ *
13
+ * @param {Signer} signer - The signer which can be either a PolkadotJs Signer or a KeyringPair.
14
+ * @param {APIConfig} apiConfig - The configuration object for the API.
15
+ * @param sdkOptions - Optional configuration for the SDK.
16
+ */
17
+ constructor(signer: ITonConnect, apiConfig: APIConfig, sdkOptions?: {
18
+ sandbox?: boolean;
19
+ apiKey?: string;
20
+ });
21
+ /**
22
+ * Fetches a quote for the given amount.
23
+ *
24
+ * @param {string | number} amount - The amount for which to fetch the quote.
25
+ * @returns {Promise<Quote>} A promise that resolves to a Quote object.
26
+ */
27
+ fetchQuote(): Promise<Quote>;
28
+ /**
29
+ * Fetches the TAO Vault address.
30
+ *
31
+ * @returns {Promise<string>} A promise that resolves to the TAO Vault address.
32
+ */
33
+ fetchVault(): Promise<{
34
+ depositVault: string;
35
+ tag?: string;
36
+ }>;
37
+ /**
38
+ * Purchases a card by transferring TAO tokens.
39
+ *
40
+ * @param params - The parameters required to purchase a card.
41
+ * @param params.walletAddress - The wallet address from which TAO tokens will be transferred.
42
+ * @param params.amount - The amount of TAO tokens to transfer.
43
+ * @returns A promise that resolves to transaction hash.
44
+ * @throws {Error} If there is not enough balance or if the transaction fails.
45
+ */
46
+ transferTon(params: {
47
+ walletAddress: string;
48
+ amount: number;
49
+ }): Promise<string>;
50
+ /**
51
+ * Retrieves the balance of the specified wallet.
52
+ *
53
+ * @param {string} wallet - The address of the wallet to get the balance for. If the address starts with "0:", it will be converted to a full address format.
54
+ * @returns {Promise<string>} - A promise that resolves to the balance of the wallet.
55
+ */
56
+ getWalletBalance(wallet: string): Promise<string>;
57
+ }