@kanalabs/aptos-smart-wallet
Version:
Typescript SDK to interact with the Aptos smart wallet
246 lines (245 loc) • 11.9 kB
JavaScript
"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.AptosWallet = void 0;
/* eslint-disable @typescript-eslint/no-explicit-any */
const aptos_1 = require("aptos");
const common_1 = require("../common");
const axios_1 = __importDefault(require("axios"));
class AptosWallet {
constructor(privateKey, options) {
this.options = options;
this.provider =
options.network === common_1.NetworkNames.AptosMainnet
? new aptos_1.Provider(aptos_1.Network.MAINNET)
: new aptos_1.Provider(aptos_1.Network.TESTNET);
const parsePrivateKey = (key) => {
const formattedKey = key.startsWith('0x') ? key.slice(2) : key;
if (formattedKey !== null) {
return new Uint8Array(formattedKey.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
}
throw new Error('Invalid key');
};
this.wallet = new aptos_1.AptosAccount(parsePrivateKey(privateKey));
this.controller = this.wallet.address().toString();
this.computeAccountAddress();
if (options.sponsor) {
this.sponsor = new aptos_1.AptosAccount(parsePrivateKey(options.sponsor));
}
}
getWalletBalance(wallet) {
return __awaiter(this, void 0, void 0, function* () {
const address = wallet ? wallet : this.address;
const chainId = 2; // For Aptos Mainnet
try {
const res = yield axios_1.default.get(`${common_1.KanaApiEndpoint}/balance/address=${address}&chainId=${chainId}`);
const balance = (yield res.data);
return balance.data;
}
catch (err) {
console.log('Error: ', err);
}
return null;
});
}
getSmartWalletDetails(wallet) {
return __awaiter(this, void 0, void 0, function* () {
const address = wallet ? wallet : this.address;
try {
const res = (yield this.provider.getAccountResource(address, common_1.SmartWalletResource));
if (res) {
const walletDetails = {
controller_address: res.data.controller_address,
wallet_address: res.data.wallet_address,
fee_payers: res.data.fee_payers,
guardians: res.data.guardians,
initialised_at: res.data.initialised_at,
};
return walletDetails;
}
}
catch (error) {
console.log(error);
}
return null;
});
}
signMessage(message) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof message === 'string') {
return this.wallet.signBuffer(Buffer.from(message)).toString();
}
return null;
});
}
computeAccountAddress() {
return __awaiter(this, void 0, void 0, function* () {
const controller_address = this.controller;
const accountAddress = yield this.viewTransaction('compute_wallet_address', [], [controller_address, this.hexToByteSeq(controller_address)]);
this.address = accountAddress[0];
return this.address;
});
}
getAccountAddress(controller) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const controller_address = controller ? controller : this.controller;
const walletAddress = (yield this.viewTransaction('get_wallet_address', [], [controller_address]));
if (((_a = walletAddress[0]) === null || _a === void 0 ? void 0 : _a.vec.length) > 0) {
return walletAddress[0].vec[0];
}
return null;
});
}
createAccount(seed, guardians, feePayers) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('create_wallet', [], [seed, [...guardians], [...feePayers]]);
});
}
changeControllerAccount(walletAddress, newController) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('change_controller', [], [walletAddress, newController]);
});
}
recoverAccount(walletAddress, newController) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('recover_wallet', [], [walletAddress, newController]);
});
}
addAccountFeePayers(walletAddress, feePayers) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('add_fee_payers', [], [walletAddress, feePayers]);
});
}
removeAccountFeePayers(walletAddress, feePayers) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('remove_fee_payers', [], [walletAddress, feePayers]);
});
}
addAccountGuardians(walletAddress, guardians) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('add_guardians', [], [walletAddress, guardians]);
});
}
removeAccountGuardians(walletAddress, guardians) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('remove_guardians', [], [walletAddress, guardians]);
});
}
depositToAccount(walletAddress, coinType, amount) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('deposit_coin', [coinType], [walletAddress, amount]);
});
}
withdrawFromAccount(walletAddress, coinType, amount) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('withdraw_coin', [coinType], [walletAddress, amount]);
});
}
transferFromAccount(walletAddress, coinType, amount) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('transfer_coin', [coinType], [walletAddress, amount]);
});
}
executeAptosFunction(wallAddress, coinTypes, payload) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.sendTransaction('execute', coinTypes, [wallAddress, ...payload]);
});
}
createAccountSponsored(seed, guardians, feePayers) {
return __awaiter(this, void 0, void 0, function* () {
if (this.options.network !== common_1.NetworkNames.AptosTestnet) {
throw new Error('Sponsored Transactions are only available on Aptos Testnet');
}
if (!this.sponsor) {
throw new Error('Sponsor not available');
}
try {
yield this.provider.getAccount(this.wallet.address());
}
catch (e) {
if ((e === null || e === void 0 ? void 0 : e.errorCode) === 'account_not_found') {
const initPayload = {
function: '0x1::aptos_account::transfer',
type_arguments: [],
arguments: [this.wallet.address(), 0],
};
const rawTxn = yield this.provider.generateTransaction(this.sponsor.address(), initPayload);
const signedTxn = yield this.provider.signTransaction(this.sponsor, rawTxn);
const transactionRes = yield this.provider.submitTransaction(signedTxn);
const result = (yield this.provider.waitForTransactionWithResult(transactionRes.hash));
if ((result === null || result === void 0 ? void 0 : result.success) !== true) {
throw new Error('Wallet initialization failed');
}
}
else {
throw new Error(`Wallet creation failed ${e}`);
}
}
const payload = {
function: '0xc73f67e94b80d8dada954fe6a6c77e8180e783b6650ef9cefc77c1931c63d9e9::SmartWallet::create_wallet',
type_arguments: [],
arguments: [seed, [...guardians], [...feePayers]],
type: 'entry_function_payload',
};
const feePayerTxn = yield this.provider.generateFeePayerTransaction(this.wallet.address(), payload, this.sponsor.address());
const senderAuth = yield this.provider.signMultiTransaction(this.wallet, feePayerTxn);
const feePayerAuth = yield this.provider.signMultiTransaction(this.sponsor, feePayerTxn);
const txn = yield this.provider.submitFeePayerTransaction(feePayerTxn, senderAuth, feePayerAuth);
const receipt = (yield this.provider.waitForTransactionWithResult(txn.hash));
return { success: receipt.success, status: receipt.vm_status, hash: txn.hash };
});
}
sendTransaction(functionName, typeArguments, args) {
return __awaiter(this, void 0, void 0, function* () {
const payload = {
function: `${common_1.SmartWalletAddress}::SmartWallet::${functionName}`,
type_arguments: typeArguments,
arguments: args,
type: 'entry_function_payload',
};
const generatedTxn = yield this.provider.generateTransaction(this.controller, payload);
const simulateTxn = yield this.provider.simulateTransaction(this.wallet, generatedTxn);
console.log('vm_status', simulateTxn[0].vm_status);
if (simulateTxn[0].success === true) {
const signedTxn = yield this.provider.signTransaction(this.wallet, generatedTxn);
const submittedTxn = yield this.provider.submitTransaction(signedTxn);
const receipt = (yield this.provider.waitForTransactionWithResult(submittedTxn.hash));
return { success: receipt.success, status: receipt.vm_status, hash: submittedTxn.hash };
}
return { success: simulateTxn[0].success, status: simulateTxn[0].vm_status };
});
}
viewTransaction(functionName, typeArguments, args) {
return __awaiter(this, void 0, void 0, function* () {
const payload = {
function: `${common_1.SmartWalletAddress}::SmartWallet::${functionName}`,
type_arguments: typeArguments,
arguments: args,
};
return yield this.provider.view(payload);
});
}
hexToByteSeq(hexString) {
return ('0x' +
hexString
.split('')
.map((char) => {
const hex = char.charCodeAt(0).toString(16);
return hex.length === 1 ? '0' + hex : hex;
})
.join(''));
}
}
exports.AptosWallet = AptosWallet;