UNPKG

@kanalabs/solver-lp-sdk

Version:
711 lines (710 loc) 36.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PaymasterSdk = void 0; const ts_sdk_1 = require("@aptos-labs/ts-sdk"); const interfaces_1 = require("./interfaces"); const constants_1 = require("./constants"); const cross_fetch_1 = __importDefault(require("cross-fetch")); const client_1 = require("@mysten/sui/client"); const transactions_1 = require("@mysten/sui/transactions"); const ed25519_1 = require("@mysten/sui/keypairs/ed25519"); const utils_1 = require("@mysten/sui/utils"); const bs58_1 = __importDefault(require("bs58")); const utils_2 = require("./utils"); // PaymasterSdk class for interacting with the Kanalabs paymaster API. class PaymasterSdk { // PaymasterSdk constructor. // @param walletProvider - Wallet provider configuration. // @param optionsLike - SDK options. constructor(walletProvider, apiKey, optionsLike) { var _a, _b; // Base URL for Gas Service API this.baseUrl = constants_1.PAYMASTER_BASE_URL; // this will make default chain as aptos , if no chain type is provided const options = Object.assign({ chain: interfaces_1.Chains.Aptos }, optionsLike); this.network = options.network; this.projectKey = options.projectKey; this.chain = options.chain; this.apiKey = apiKey; switch (options.chain) { case interfaces_1.Chains.Aptos: { if (options.network !== interfaces_1.Network.MAINNET && options.network !== interfaces_1.Network.TESTNET && options.network !== undefined) { throw new Error('Invalid network'); } const config = new ts_sdk_1.AptosConfig({ network: (_a = options.network) !== null && _a !== void 0 ? _a : interfaces_1.Network.MAINNET, fullnode: options.nodeUrl !== null ? options.nodeUrl : options.network === interfaces_1.Network.TESTNET ? constants_1.TESTNET_NODE_URL : constants_1.MAINNET_NODE_URL, }); this.aptosClient = new ts_sdk_1.Aptos(config); this.wallet = walletProvider.privateKey ? ts_sdk_1.Account.fromPrivateKey({ privateKey: new ts_sdk_1.Ed25519PrivateKey(walletProvider.privateKey), }) : undefined; break; } case interfaces_1.Chains.Sui: { const suiNodeUrl = (_b = options.nodeUrl) !== null && _b !== void 0 ? _b : (optionsLike.network === interfaces_1.Network.TESTNET ? constants_1.SUI_TESTNET_NODE_URL : constants_1.SUI_MAINNET_NODE_URL); this.suiClient = new client_1.SuiClient({ url: suiNodeUrl }); this.suiwallet = walletProvider.privateKey ? ed25519_1.Ed25519Keypair.fromSecretKey((0, utils_1.fromHex)(walletProvider.privateKey)) : undefined; break; } default: { throw new Error(`Invalid Chain` + options.chain); } } } // Initialize the user's account. // @returns Success and message information. initAccount(args) { var _a; return __awaiter(this, void 0, void 0, function* () { let address; switch (this.chain) { case interfaces_1.Chains.Aptos: { address = (args === null || args === void 0 ? void 0 : args.address) ? args.address : this.wallet ? this.wallet.accountAddress.toString() : (() => { throw new Error('No address provided'); })(); break; } case interfaces_1.Chains.Sui: { if (!args.address) { throw new Error('No address provided'); } address = args === null || args === void 0 ? void 0 : args.address; break; } default: { throw new Error('Unsupported Chain'); } } const url = `${this.baseUrl}/initAccount`; const query = { address: address, coin: (_a = args === null || args === void 0 ? void 0 : args.coin) !== null && _a !== void 0 ? _a : '', chain: this.chain }; const params = new URLSearchParams(query).toString(); const headers = this.getCommonHeaders(); try { const response = yield (0, cross_fetch_1.default)(`${url}?${params}`, { headers }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in initializing Aptos account for user.'); }); } return yield response.json(); } catch (error) { console.log('error', error); throw (error === null || error === void 0 ? void 0 : error.data) || (error === null || error === void 0 ? void 0 : error.message) || error; } }); } //Add a new Fee payer to DApp addFeePayer() { return __awaiter(this, void 0, void 0, function* () { const headers = this.getCommonHeaders(); console.log(headers); const url = `${this.baseUrl}/addNewFeepayer`; try { const response = yield (0, cross_fetch_1.default)(`${url}`, { headers }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error at Adding new Fee payer in DApp'); }); } const responseData = yield response.json(); return responseData.feePayerAddress; } catch (error) { console.log('error', error); throw (error === null || error === void 0 ? void 0 : error.data) || (error === null || error === void 0 ? void 0 : error.message) || error; } }); } // Add the user to the whitelist. // @returns Success and message information. addToWhitelist(args) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.baseUrl}/addToWhitelist`; let address; switch (this.chain) { case interfaces_1.Chains.Aptos: { address = (args === null || args === void 0 ? void 0 : args.address) ? args.address : this.wallet ? this.wallet.accountAddress.toString() : (() => { throw new Error('No address provided'); })(); break; } case interfaces_1.Chains.Sui: { address = (args === null || args === void 0 ? void 0 : args.address) ? args.address : this.suiwallet ? this.suiwallet.getPublicKey().toSuiAddress() : (() => { throw new Error('No address provided'); })(); break; } default: { throw new Error('Unsupported Chain'); } } const query = { user_address: address, chain: this.chain }; const params = new URLSearchParams(query).toString(); const headers = this.getCommonHeaders(); try { const response = yield (0, cross_fetch_1.default)(`${url}?${params}`, { headers, method: 'GET' }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in adding user to whitelist.'); }); } return yield response.json(); } catch (error) { throw (error === null || error === void 0 ? void 0 : error.data) || error; } }); } // Disables user on the whitelist to stop sponsored txns. // @returns Success and message information. disableUser(args) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.baseUrl}/modifyUserState`; const address = (args === null || args === void 0 ? void 0 : args.address) ? args.address : this.wallet ? this.wallet.accountAddress.toString() : (() => { throw new Error('No address provided'); })(); const query = { user_address: address, status: 'false' }; const params = new URLSearchParams(query).toString(); const headers = this.getCommonHeaders(); try { const response = yield (0, cross_fetch_1.default)(`${url}?${params}`, { headers, method: 'GET' }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in disabling user.'); }); } return yield response.json(); } catch (error) { throw (error === null || error === void 0 ? void 0 : error.data) || error; } }); } // Enables user on the whitelist to start sponsored txns. // @returns Success and message information. enableUser(args) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.baseUrl}/modifyUserState`; const address = (args === null || args === void 0 ? void 0 : args.address) ? args.address : this.wallet ? this.wallet.accountAddress.toString() : (() => { throw new Error('No address provided'); })(); const query = { user_address: address, status: 'true' }; const params = new URLSearchParams(query).toString(); const headers = this.getCommonHeaders(); try { const response = yield (0, cross_fetch_1.default)(`${url}?${params}`, { headers, method: 'GET' }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in enabling user.'); }); } return yield response.json(); } catch (error) { throw (error === null || error === void 0 ? void 0 : error.data) || error; } }); } // Check if the user is whitelisted. // @returns Success and message information. isWhitelisted(args) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.baseUrl}/isWhitelisted`; let address; switch (this.chain) { case interfaces_1.Chains.Aptos: { address = (args === null || args === void 0 ? void 0 : args.address) ? args.address : this.wallet ? this.wallet.accountAddress.toString() : (() => { throw new Error('No address provided'); })(); break; } case interfaces_1.Chains.Sui: { if (!args.address) { throw new Error('No address provided'); } address = args === null || args === void 0 ? void 0 : args.address; break; } default: { throw new Error('Unsupported Chain'); } } const query = { address: address }; const params = new URLSearchParams(query).toString(); const headers = this.getCommonHeaders(); try { const response = yield (0, cross_fetch_1.default)(`${url}?${params}`, { headers, method: 'GET' }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in checking whitelist status.'); }); } return yield response.json(); } catch (error) { throw (error === null || error === void 0 ? void 0 : error.data) || error; } }); } // Perform a sponsored transaction. // @param payload - Transaction payload. // @returns Pending transaction information. sponsoredTxn(args) { var _a; return __awaiter(this, void 0, void 0, function* () { try { if (this.wallet === undefined) { throw new Error('No wallet'); } const transaction = yield this.aptosClient.transaction.build.simple({ sender: this.wallet.accountAddress.toString(), data: args.data, options: args.options, withFeePayer: true, }); const senderAuth = this.aptosClient.transaction.sign({ signer: this.wallet, transaction, }); const rawTransactionBytes = transaction.rawTransaction.bcsToBytes(); const url = `${this.baseUrl}/sponsorGas`; const headers = this.getCommonHeaders(); const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ data: rawTransactionBytes }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); const feePayerAddress = responseData.feePayerAddress; const feepayerSignature = new Uint8Array(Object.values(responseData.feePayerAuth)); const deserializerFeePayer = new ts_sdk_1.Deserializer(feepayerSignature); const feepayerAuth = ts_sdk_1.AccountAuthenticator.deserialize(deserializerFeePayer); const committedTxn = yield this.aptosClient.transaction.submit.simple({ transaction: { rawTransaction: transaction.rawTransaction, feePayerAddress: ts_sdk_1.AccountAddress.fromString(feePayerAddress), }, senderAuthenticator: senderAuth, feePayerAuthenticator: feepayerAuth, }); return committedTxn; } catch (error) { throw ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) || error; } }); } sponseredSuiTxn(args) { var _a; return __awaiter(this, void 0, void 0, function* () { try { if (this.suiwallet === undefined) { throw new Error('No wallet'); } const provider = this.suiClient; const senderAddress = this.suiwallet.getPublicKey().toSuiAddress(); const kindBytes = yield args.transactionBlock.build({ client: provider, onlyTransactionKind: true }); const serialized = transactions_1.Transaction.fromKind(kindBytes).serialize(); // call fee payer data here const url = `${this.baseUrl}/sponsorGas`; const headers = this.getCommonHeaders(); const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ data: serialized, chain: interfaces_1.Chains.Sui, senderAddress }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); if (!responseData.feePayerAuth) { throw new Error('Sponser Signature not found'); } if (!responseData.serializedResponse) { throw new Error('Serialized Sponser Transaction not found'); } const sponsoredTx = transactions_1.Transaction.from(responseData.serializedResponse); const fullSerializedTx = yield sponsoredTx.build({ client: provider }); const userSignature = yield this.suiwallet.signTransaction(fullSerializedTx); const result = yield provider.executeTransactionBlock({ transactionBlock: fullSerializedTx, signature: [userSignature.signature, responseData.feePayerAuth], }); const responseTX = yield (0, utils_2.waitForTransactionConfirmation)(provider, result.digest); return responseTX; } catch (error) { throw ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) || error; } }); } sponserLiquidity(args) { var _a; return __awaiter(this, void 0, void 0, function* () { try { const url = `${this.baseUrl}/sponserLiquidity`; const headers = this.getCommonHeaders(); const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ recieptant: args.recieptant, amount: args.amount, coinType: args.coinType, chain: this.chain, feePayer: args.feePayer }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); if (this.chain === interfaces_1.Chains.Aptos) { if (!this.aptosClient) { throw new Error('No Aptos Provider'); } if (!responseData.txHash) { throw new Error('No Transaction Hash in sponser Transaction Response'); } const txnReceipt = yield this.aptosClient.waitForTransaction({ transactionHash: responseData.txHash, options: { checkSuccess: true, }, }); return txnReceipt.hash; } else if (this.chain === interfaces_1.Chains.Sui) { if (!responseData.signature) { throw new Error('Sponser Signature not found'); } if (!responseData.serializedResponse) { throw new Error('Serialized Sponser Transaction not found'); } if (!this.suiClient) { throw new Error('No Sui Provider'); } const provider = this.suiClient; const sponsoredTx = transactions_1.Transaction.from(responseData.serializedResponse); const fullSerializedTx = yield sponsoredTx.build({ client: provider }); const result = yield this.suiClient.executeTransactionBlock({ transactionBlock: fullSerializedTx, signature: [responseData.signature], }); const responseTX = yield (0, utils_2.waitForTransactionConfirmation)(provider, result.digest); return responseTX.digest; } else { throw new Error('Unsupported Chain'); } } catch (error) { throw ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) || error; } }); } swapTokens(args) { var _a; return __awaiter(this, void 0, void 0, function* () { try { if (this.chain === interfaces_1.Chains.Aptos) { if (!this.aptosClient) { throw new Error('No Aptos Provider'); } const url = `${this.baseUrl}/swapTokens`; const headers = this.getCommonHeaders(); const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ sponserAddress: args.sponserAddress, amount: args.amountIn, coinType: args.fromToken, data: args.data, options: args.options, }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); if (!responseData.txHash) { throw new Error('No Transaction Hash in sponser Transaction Response'); } const txnReceipt = yield this.aptosClient.waitForTransaction({ transactionHash: responseData.txHash, options: { checkSuccess: true, }, }); return txnReceipt.hash; } else if (this.chain === interfaces_1.Chains.Sui) { const provider = this.suiClient; const url = `${this.baseUrl}/swapTokens`; const headers = this.getCommonHeaders(); const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ chain: interfaces_1.Chains.Sui, sponserAddress: args.sponserAddress, amount: args.amountIn, coinType: args.fromToken, serializedData: args.data, }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); if (!responseData.signature) { throw new Error('Sponser Signature not found'); } if (!responseData.serializedResponse) { throw new Error('Serialized Sponser Transaction not found'); } // const sponsoredTx = TransactionBlock.from(responseData.serializedResponse) // const fullSerializedTx = await sponsoredTx.build({ provider }) const decodedTx = bs58_1.default.decode(args.data); const result = yield provider.executeTransactionBlock({ transactionBlock: decodedTx, signature: [responseData.signature], }); const responseTX = yield (0, utils_2.waitForTransactionConfirmation)(provider, result.digest); return responseTX.digest; } else { throw new Error('Unsupported Chain'); } } catch (error) { throw ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) || error; } }); } deposit(args) { var _a; return __awaiter(this, void 0, void 0, function* () { try { const url = `${this.baseUrl}/deposit`; const headers = this.getCommonHeaders(); const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ senderAddress: args.senderAddress, amount: args.amount, coinType: args.coinType, reciever: args.reciever, splitCount: args.splitCount, }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); const txData = new Uint8Array(Object.values(responseData.txData)); const signature = yield this.suiwallet.signTransaction(txData); const res = yield this.suiClient.executeTransactionBlock({ transactionBlock: txData, signature: signature.signature, }); const responseTX = yield (0, utils_2.waitForTransactionConfirmation)(this.suiClient, res.digest); return responseTX.digest; } catch (error) { console.log(error); throw ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) || error; } }); } /// Perform a sponsored transaction with senderAuth and transaction bytes. /// @param transaction - Generated transaction. SimpleTransaction or MultiAgentTransaction. /// @param senderAuth - Sender authenticator. /// @param additionalAuthenticators - Additional signer authenticators. /// @param additionalAddresses - Secondary signer addresses. /// @returns Pending transaction information. sponsoredTxnWithSenderAuth(args) { var _a; return __awaiter(this, void 0, void 0, function* () { try { const { transaction, senderAuth, additionalAuthenticators, additionalAddresses } = args; const rawTransactionBytes = transaction.rawTransaction.bcsToBytes(); const url = `${this.baseUrl}/sponsorGas`; const headers = this.getCommonHeaders(); const requestBody = { data: rawTransactionBytes }; if (additionalAuthenticators && additionalAddresses) { if (additionalAuthenticators.length !== additionalAddresses.length) { throw new Error('No of Additional Authenticators and address length mismatch'); } requestBody.additionalSigners = additionalAddresses.map((address) => address.toString()); } const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify(requestBody), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in sponsoring transaction.'); }); } const responseData = yield response.json(); const feePayerAddress = responseData.feePayerAddress; const feepayerSignature = new Uint8Array(Object.values(responseData.feePayerAuth)); const deserializerFeePayer = new ts_sdk_1.Deserializer(feepayerSignature); const feepayerAuth = ts_sdk_1.AccountAuthenticator.deserialize(deserializerFeePayer); if (additionalAuthenticators && additionalAddresses) { // For multi agent transaction return yield this.aptosClient.transaction.submit.multiAgent({ transaction: { rawTransaction: transaction.rawTransaction, feePayerAddress: ts_sdk_1.AccountAddress.fromString(feePayerAddress), secondarySignerAddresses: additionalAddresses, }, senderAuthenticator: senderAuth, feePayerAuthenticator: feepayerAuth, additionalSignersAuthenticators: additionalAuthenticators, }); } else { // For simple transaction return yield this.aptosClient.transaction.submit.simple({ transaction: { rawTransaction: transaction.rawTransaction, feePayerAddress: ts_sdk_1.AccountAddress.fromString(feePayerAddress), }, senderAuthenticator: senderAuth, feePayerAuthenticator: feepayerAuth, }); } } catch (error) { throw ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) || error; } }); } addWhitelistFunctions(args) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.baseUrl}/addWhitelistFunctions`; const headers = this.getCommonHeaders(); try { // Send a POST request to the server with the functions data in the body const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ functions: args.functions }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in adding whitelist functions.'); }); } return yield response.json(); } catch (error) { throw (error === null || error === void 0 ? void 0 : error.data) || error; } }); } addModuleWhitelistFunctions(args) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.baseUrl}/addModuleWhitelistFunctions`; const headers = this.getCommonHeaders(); try { // Send a POST request to the server with the functions data in the body const response = yield (0, cross_fetch_1.default)(url, { method: 'POST', headers: headers, body: JSON.stringify({ functions: args.functions }), }); if (response.status >= 400) { yield response.json().then((data) => { throw new Error((data === null || data === void 0 ? void 0 : data.error) || (data === null || data === void 0 ? void 0 : data.message) || 'Error in adding module whitelist functions.'); }); } return yield response.json(); } catch (error) { throw (error === null || error === void 0 ? void 0 : error.data) || error; } }); } // Get common headers for requests. // @returns Common headers. getCommonHeaders() { var _a, _b; return { 'Content-Type': 'application/json', 'x-api-key': this.apiKey, 'api-key': this.projectKey, network: (_a = this.network) !== null && _a !== void 0 ? _a : interfaces_1.Network.MAINNET, chain: (_b = this.chain) !== null && _b !== void 0 ? _b : interfaces_1.Chains.Aptos, }; } } exports.PaymasterSdk = PaymasterSdk;