您现在的位置:kastop>> Kas信息 Kaspa网络>>正文内容

Kaspa钱包ts代码封装

文章目录

1. 配置wasm

2. 钱包地址创建

3. KAS转账&余额查询

4. KRC-20 处理

5. 使用demo


1. 配置wasm

下载wasm地址:https://kaspa.aspectron.org/nightly/downloads/


在项目根目录下添加wasm目录, 将下载的wasm文件中web目录下kaspa和kaspa-dev文件家复制到项目wasm下


2. 钱包地址创建

import { EventEmitter } from 'events';

import {

    kaspaToSompi,

    type IPaymentOutput,

    createTransactions,

    PrivateKey,

    UtxoProcessor,

    UtxoContext,

    RpcClient

} from "../wasm/kaspa-dev";

class TransactionSender extends EventEmitter {

    private networkId: string;

    private privateKey: PrivateKey;

    private processor: UtxoProcessor;

    private context: UtxoContext;

    private rpc: RpcClient;

    constructor(networkId: string, privKey: PrivateKey, rpc: RpcClient) {

        super();

        this.networkId = networkId;

        this.privateKey = privKey;

        this.processor = new UtxoProcessor({ rpc, networkId });

        this.rpc = this.processor.rpc;

        this.context = new UtxoContext({ processor: this.processor });

        this.registerProcessor();

    }

    async transferFunds(address: string, amount: string): Promise<string> {

        const payments: IPaymentOutput[] = [{

            address: address,

            amount: kaspaToSompi(amount)!

        }];

        return await this.send(payments);

    }

    private async send(outputs: IPaymentOutput[]): Promise<string> {

        const { transactions, summary } = await createTransactions({

            entries: this.context,

            outputs,

            changeAddress: this.privateKey.toPublicKey().toAddress(this.networkId).toString(),

            priorityFee: kaspaToSompi("0.02")

        });

        for (let i = 0; i < transactions.length; i++) {

            await this.submitTransaction(transactions[i]);

        }

        return summary.finalTransactionId;

    }

    private async submitTransaction(transaction: any) {

        transaction.sign([this.privateKey]);

        await transaction.submit(this.rpc);

    }

    private registerProcessor() {

        this.processor.addEventListener("utxo-proc-start", async () => {

            await this.context.clear();

            await this.context.trackAddresses([this.privateKey.toPublicKey().toAddress(this.networkId).toString()]);

        });

        this.processor.start();

    }

}

export default TransactionSender;


3. KAS转账&余额查询


class Sender {

    public client: RpcClient;

    private network: string;

    constructor(network: string = 'testnet-10') {

        this.network = network;

        this.client = new RpcClient({

            // url: "127.0.0.1",

            resolver: new Resolver(),

            encoding: Encoding.Borsh,

            networkId: network

        });

    }

    public async connect() {

        await this.client.connect();

    }

    public async disconnect() {

        await this.client.disconnect();

    }

    public async getServerInfo(): Promise<IGetServerInfoResponse> {

        return await this.client.getServerInfo()

    }

    public async transfer(fromPrivateKey: string, address: string, amount: string): Promise<string> {

        try {

            const privateKey = new PrivateKey(fromPrivateKey);

            const sourceAddress = privateKey.toKeypair().toAddress(this.network);

            let { entries } = (await this.client.getUtxosByAddresses([sourceAddress]));

            const payments: IPaymentOutput[] = [{

                address: address,

                amount: kaspaToSompi(amount)!

            }];

            return await this.send(privateKey, entries, payments);

        } catch (error) {

            return error

        }

    }

    // 使用createTransaction 构建交易 signTransaction 签名

    // 备注: output 需要自己构建fee以及输出(不然会吞掉所有账户余额),

    public async transfer1(fromPrivateKey: string, address: string, amount: string): Promise<string> {

        try {

            const privateKey = new PrivateKey(fromPrivateKey);

            const sourceAddress = privateKey.toKeypair().toAddress(this.network);

            let { entries } = (await this.client.getUtxosByAddresses([sourceAddress]));

            if (entries.length === 0) {

                return;

            }

            let total = entries.reduce((agg, curr) => {

                return curr.amount + agg;

            }, 0n);

            // 手续费设置

            let fee = BigInt(100000000);

            const output: IPaymentOutput[] = [{

                address: address,

                amount: kaspaToSompi(amount)!

            },

            // 构建当前地址余额输出

            {

                address: sourceAddress,

                amount: total - kaspaToSompi(amount)! - fee

            }];

            const tx = createTransaction(entries, output, fee, "", 1);

            console.info("Transaction before signing:", tx);

            const transaction = signTransaction(tx, [privateKey], true);

            console.log("Transaction:", transaction);

            let resp = await this.client.submitTransaction({ transaction });

            return resp.transactionId;

        } catch (error) {

            return error

        }

    }

    private async send(privateKey: PrivateKey, entries: UtxoEntryReference[], outputs: IPaymentOutput[]): Promise<string> {

        // return

        const { transactions, summary } = await createTransactions({

            entries: entries,

            outputs,

            changeAddress: privateKey.toPublicKey().toAddress(this.network).toString(),

            priorityFee: {

                amount: kaspaToSompi("0.0001"),

            },

            networkId: this.network,

        });

        // return

        for (const transaction of transactions) {

            transaction.sign([privateKey]);

            await transaction.submit(this.client);

        }

        return summary.finalTransactionId;

    }

    // Method to get the balance of the address

    public async getBalance(address: string): Promise<IGetBalanceByAddressResponse> {

        const balanceRequest: IGetBalanceByAddressRequest = {

            address: address,

        };

        return this.client.getBalanceByAddress(balanceRequest);

    }

}

import {

    RpcClient,

    Encoding,

    Resolver,

    PrivateKey,

    IGetServerInfoResponse,

    type IPaymentOutput,

    kaspaToSompi,

    createTransactions,

    createTransaction,

    signTransaction,

    IGetBalanceByAddressResponse, FeeSource

} from "../wasm/kaspa-dev";

import { IGetBalanceByAddressRequest, UtxoEntryReference } from "../wasm/kaspa";

export default Sender;


4. KRC - 20 处理


import {

    RpcClient, Encoding, Resolver, ScriptBuilder, Opcodes, PrivateKey,

    addressFromScriptPublicKey, createTransactions, kaspaToSompi, createTransaction, calculateTransactionFee

} from "../wasm/kaspa";

const u64MaxValue = 18446744073709551615;

const baseKasToP2SHAddress = "1.3";

export interface KRC20Data {

    p: "krc-20";

    op: 'mint' | 'deploy' | 'transfer';

    tick: string;

    to?: string;

    amt?: string;

    max?: string;

    lim?: string;

    dec?: "8";

    pre?: string;

}

class KRC20 {

    public client: RpcClient;

    private network: string;

    constructor(network: string = 'testnet-10') {

        this.network = network;

        this.client = new RpcClient({

            resolver: new Resolver(),

            encoding: Encoding.Borsh,

            networkId: network

        });

    }

    public async connect() {

        await this.client.connect();

    }

    public async disconnect() {

        await this.client.disconnect();

    }

    public async mint(_privateKey: string, data: KRC20Data) {

        return this.send(_privateKey, data)

    }

    public async deploy(_privateKey: string, data: KRC20Data) {

        return this.send(_privateKey, data)

    }

    public async transfer(_privateKey: string, data: KRC20Data) {

        return this.send(_privateKey, data)

    }

    public async send(_privateKey: string, data: KRC20Data) {

        const privateKey = new PrivateKey(_privateKey);

        const publicKey = privateKey.toPublicKey();

        const address = publicKey.toAddress(this.network);

        const script = new ScriptBuilder()

            .addData(privateKey.toPublicKey().toXOnlyPublicKey().toString())

            .addOp(Opcodes.OpCheckSig)

            .addOp(Opcodes.OpFalse)

            .addOp(Opcodes.OpIf)

            .addData(Buffer.from("kasplex"))

            .addI64(0n)

            .addData(Buffer.from(JSON.stringify(data, null, 0)))

            .addOp(Opcodes.OpEndIf);

        let scriptPublicKey = script.createPayToScriptHashScript()

        const P2SHAddress = addressFromScriptPublicKey(scriptPublicKey, this.network)!;

        try {

            const { entries } = await this.client.getUtxosByAddresses({ addresses: [address.toString()] });

            const { transactions, summary } = await createTransactions({

                priorityEntries: [],

                entries,

                outputs: [{

                    address: P2SHAddress.toString(),

                    amount: kaspaToSompi(baseKasToP2SHAddress)!

                }],

                changeAddress: address.toString(),

                priorityFee: kaspaToSompi("0"),

                networkId: this.network

            });

            for (const transaction of transactions) {

                transaction.sign([privateKey]);

                await transaction.submit(this.client);

            }

            const hash = summary.finalTransactionId

            console.log(`summary finalTransactionId transaction on: ${hash}`, 'INFO');

            var revealEntries = [{

                "address": P2SHAddress.toString(),

                "amount": kaspaToSompi(baseKasToP2SHAddress)!,

                "outpoint": {

                    "transactionId": hash,

                    "index": 0

                },

                "scriptPublicKey": "0000" + scriptPublicKey.script,

                "blockDaaScore": u64MaxValue,

                "isCoinbase": false

            }];

            var fee = kaspaToSompi(this.getFee(data.op))!.valueOf()

            let tx = createTransaction(revealEntries, [], kaspaToSompi("0")!)

            fee = fee + calculateTransactionFee(this.network, tx).valueOf()

            return await this.sendRevealTransaction(privateKey, address, revealEntries, script, fee)

        } catch (error) {

            return error

        }

    }

    // Helper function to determine the KASPA amount based on the operation type

    private getFee(optype): string {

        switch (optype) {

            case 'deploy':

                return "1000";

            case 'mint':

                return "1";

            case 'transfer':

                return "1";

            default:

                return "2";  // Default to "2" if the operation is unknown

        }

    }

    public async sendRevealTransaction(privateKey, address, revealEntries, script, fee) {

        const { transactions, summary } = await createTransactions({

            priorityEntries: revealEntries,

            entries: revealEntries,

            outputs: [],

            changeAddress: address.toString(),

            priorityFee: fee,

            networkId: this.network

        });

        for (const transaction of transactions) {

            transaction.sign([privateKey], false);

            const ourOutput = transaction.transaction.inputs.findIndex((input) => input.signatureScript === '');

            if (ourOutput !== -1) {

                const signature = await transaction.createInputSignature(ourOutput, privateKey);

                transaction.fillInput(ourOutput, script.encodePayToScriptHashSignatureScript(signature));

            }

            await transaction.submit(this.client);

        }

        return summary.finalTransactionId

    }

}

export default KRC20;




5. 使用demo

import Rpc from "./src/transaction";

import KRC20 from "./src/script";

//   -------------------------------------- server information --------------------------------------

// let rpc = new Rpc()

// await rpc.connect()

// let serverInfo = await rpc.getServerInfo()

// console.log("serverInfo;",serverInfo)

// if (!serverInfo.isSynced || !serverInfo.hasUtxoIndex) {

//   await rpc.disconnect();

//   process.exit(1);

// }

//   -------------------------------------- KAS balance--------------------------------------

// let rpc = new Rpc()

// await rpc.connect()

// let address = "kaspatest:*******"

// let balance = await rpc.getBalance(address)

// console.log("balance:", balance)

//   -------------------------------------- transfer KAS --------------------------------------

// let rpc = new Rpc()

// await rpc.connect()

// let privateKey = "****"

// let address = "kaspatest:****"

// let amount = "1"

// let txhash = await rpc.transfer(privateKey, address, amount)

// console.log("txhash;",txhash)

//   -------------------------------------- mint --------------------------------------

let privateKey = "*****"

let krc20 = new KRC20()

await krc20.connect()

var mintdata = {

    p: "krc-20",

    op: 'mint',

    tick: "****"

}

let txid = await krc20.mint(privateKey, mintdata)

console.log("txsh", txid)

// -------------------------------------- transfer --------------------------------------

// let krc20 = new KRC20()

// let privateKey = "****"

// await krc20.connect()

// var transferdata = {

//     p: "krc-20",

//     op: 'transfer',

//     tick: "SNOWDN",

//     to: "kaspatest:****",

//     amt: "1000000000",

// }

// let txid = await krc20.transfer(privateKey, transferdata)

// console.log("txsh", txid)

// -------------------------------------- deploy --------------------------------------

// let krc20 = new KRC20()

// await krc20.connect()

// var deploydata = {

//     p: "krc-20",

//     op: 'deploy',

//     tick: "JEMES1",

//     to: "kaspatest:*****",

//     amt: "1000000000",

//     max: "1000000000000000",

//     lim: "1000000000",

//     dec: "8",

//     pre: "1000000000000000",

// }

// let txid = await krc20.deploy(privateKey, deploydata)

// console.log("txsh", txid)

process.exit(1);

class Sender {

    public client: RpcClient;

    private network: string;

    constructor(network: string = 'testnet-10') {

        this.network = network;

        this.client = new RpcClient({

            // url: "127.0.0.1",

            resolver: new Resolver(),

            encoding: Encoding.Borsh,

            networkId: network

        });

    }

    public async connect() {

        await this.client.connect();

    }

    public async disconnect() {

        await this.client.disconnect();

    }

    public async getServerInfo(): Promise<IGetServerInfoResponse> {

        return await this.client.getServerInfo()

    }

    public async transfer(fromPrivateKey: string, address: string, amount: string): Promise<string> {

        try {

            const privateKey = new PrivateKey(fromPrivateKey);

            const sourceAddress = privateKey.toKeypair().toAddress(this.network);

            let { entries } = (await this.client.getUtxosByAddresses([sourceAddress]));

            const payments: IPaymentOutput[] = [{

                address: address,

                amount: kaspaToSompi(amount)!

            }];

            return await this.send(privateKey, entries, payments);

        } catch (error) {

            return error

        }

    }

    // 使用createTransaction 构建交易 signTransaction 签名

    // 备注: output 需要自己构建fee以及输出(不然会吞掉所有账户余额),

    public async transfer1(fromPrivateKey: string, address: string, amount: string): Promise<string> {

        try {

            const privateKey = new PrivateKey(fromPrivateKey);

            const sourceAddress = privateKey.toKeypair().toAddress(this.network);

            let { entries } = (await this.client.getUtxosByAddresses([sourceAddress]));

            if (entries.length === 0) {

                return;

            }

            let total = entries.reduce((agg, curr) => {

                return curr.amount + agg;

            }, 0n);

            // 手续费设置

            let fee = BigInt(100000000);

            const output: IPaymentOutput[] = [{

                address: address,

                amount: kaspaToSompi(amount)!

            },

            // 构建当前地址余额输出

            {

                address: sourceAddress,

                amount: total - kaspaToSompi(amount)! - fee

            }];

            const tx = createTransaction(entries, output, fee, "", 1);

            console.info("Transaction before signing:", tx);

            const transaction = signTransaction(tx, [privateKey], true);

            console.log("Transaction:", transaction);

            let resp = await this.client.submitTransaction({ transaction });

            return resp.transactionId;

        } catch (error) {

            return error

        }

    }

    private async send(privateKey: PrivateKey, entries: UtxoEntryReference[], outputs: IPaymentOutput[]): Promise<string> {

        // return

        const { transactions, summary } = await createTransactions({

            entries: entries,

            outputs,

            changeAddress: privateKey.toPublicKey().toAddress(this.network).toString(),

            priorityFee: {

                amount: kaspaToSompi("0.0001"),

            },

            networkId: this.network,

        });

        // return

        for (const transaction of transactions) {

            transaction.sign([privateKey]);

            await transaction.submit(this.client);

        }

        return summary.finalTransactionId;

    }

    // Method to get the balance of the address

    public async getBalance(address: string): Promise<IGetBalanceByAddressResponse> {

        const balanceRequest: IGetBalanceByAddressRequest = {

            address: address,

        };

        return this.client.getBalanceByAddress(balanceRequest);

    }

}

import {

    RpcClient,

    Encoding,

    Resolver,

    PrivateKey,

    IGetServerInfoResponse,

    type IPaymentOutput,

    kaspaToSompi,

    createTransactions,

    createTransaction,

    signTransaction,

    IGetBalanceByAddressResponse, FeeSource

} from "../wasm/kaspa-dev";

import { IGetBalanceByAddressRequest, UtxoEntryReference } from "../wasm/kaspa";

export default Sender;

4. KRC - 20 处理

import {

    RpcClient, Encoding, Resolver, ScriptBuilder, Opcodes, PrivateKey,

    addressFromScriptPublicKey, createTransactions, kaspaToSompi, createTransaction, calculateTransactionFee

} from "../wasm/kaspa";

const u64MaxValue = 18446744073709551615;

const baseKasToP2SHAddress = "1.3";

export interface KRC20Data {

    p: "krc-20";

    op: 'mint' | 'deploy' | 'transfer';

    tick: string;

    to?: string;

    amt?: string;

    max?: string;

    lim?: string;

    dec?: "8";

    pre?: string;

}

class KRC20 {

    public client: RpcClient;

    private network: string;

    constructor(network: string = 'testnet-10') {

        this.network = network;

        this.client = new RpcClient({

            resolver: new Resolver(),

            encoding: Encoding.Borsh,

            networkId: network

        });

    }

    public async connect() {

        await this.client.connect();

    }

    public async disconnect() {

        await this.client.disconnect();

    }

    public async mint(_privateKey: string, data: KRC20Data) {

        return this.send(_privateKey, data)

    }

    public async deploy(_privateKey: string, data: KRC20Data) {

        return this.send(_privateKey, data)

    }

    public async transfer(_privateKey: string, data: KRC20Data) {

        return this.send(_privateKey, data)

    }

    public async send(_privateKey: string, data: KRC20Data) {

        const privateKey = new PrivateKey(_privateKey);

        const publicKey = privateKey.toPublicKey();

        const address = publicKey.toAddress(this.network);

        const script = new ScriptBuilder()

            .addData(privateKey.toPublicKey().toXOnlyPublicKey().toString())

            .addOp(Opcodes.OpCheckSig)

            .addOp(Opcodes.OpFalse)

            .addOp(Opcodes.OpIf)

            .addData(Buffer.from("kasplex"))

            .addI64(0n)

            .addData(Buffer.from(JSON.stringify(data, null, 0)))

            .addOp(Opcodes.OpEndIf);

        let scriptPublicKey = script.createPayToScriptHashScript()

        const P2SHAddress = addressFromScriptPublicKey(scriptPublicKey, this.network)!;

        try {

            const { entries } = await this.client.getUtxosByAddresses({ addresses: [address.toString()] });

            const { transactions, summary } = await createTransactions({

                priorityEntries: [],

                entries,

                outputs: [{

                    address: P2SHAddress.toString(),

                    amount: kaspaToSompi(baseKasToP2SHAddress)!

                }],

                changeAddress: address.toString(),

                priorityFee: kaspaToSompi("0"),

                networkId: this.network

            });

            for (const transaction of transactions) {

                transaction.sign([privateKey]);

                await transaction.submit(this.client);

            }

            const hash = summary.finalTransactionId

            console.log(`summary finalTransactionId transaction on: ${hash}`, 'INFO');

            var revealEntries = [{

                "address": P2SHAddress.toString(),

                "amount": kaspaToSompi(baseKasToP2SHAddress)!,

                "outpoint": {

                    "transactionId": hash,

                    "index": 0

                },

                "scriptPublicKey": "0000" + scriptPublicKey.script,

                "blockDaaScore": u64MaxValue,

                "isCoinbase": false

            }];

            var fee = kaspaToSompi(this.getFee(data.op))!.valueOf()

            let tx = createTransaction(revealEntries, [], kaspaToSompi("0")!)

            fee = fee + calculateTransactionFee(this.network, tx).valueOf()

            return await this.sendRevealTransaction(privateKey, address, revealEntries, script, fee)

        } catch (error) {

            return error

        }

    }

    // Helper function to determine the KASPA amount based on the operation type

    private getFee(optype): string {

        switch (optype) {

            case 'deploy':

                return "1000";

            case 'mint':

                return "1";

            case 'transfer':

                return "1";

            default:

                return "2";  // Default to "2" if the operation is unknown

        }

    }

    public async sendRevealTransaction(privateKey, address, revealEntries, script, fee) {

        const { transactions, summary } = await createTransactions({

            priorityEntries: revealEntries,

            entries: revealEntries,

            outputs: [],

            changeAddress: address.toString(),

            priorityFee: fee,

            networkId: this.network

        });

        for (const transaction of transactions) {

            transaction.sign([privateKey], false);

            const ourOutput = transaction.transaction.inputs.findIndex((input) => input.signatureScript === '');

            if (ourOutput !== -1) {

                const signature = await transaction.createInputSignature(ourOutput, privateKey);

                transaction.fillInput(ourOutput, script.encodePayToScriptHashSignatureScript(signature));

            }

            await transaction.submit(this.client);

        }

        return summary.finalTransactionId

    }

}

export default KRC20;


5. 使用demo


import Rpc from "./src/transaction";

import KRC20 from "./src/script";

//   -------------------------------------- server information --------------------------------------

// let rpc = new Rpc()

// await rpc.connect()

// let serverInfo = await rpc.getServerInfo()

// console.log("serverInfo;",serverInfo)

// if (!serverInfo.isSynced || !serverInfo.hasUtxoIndex) {

//   await rpc.disconnect();

//   process.exit(1);

// }

//   -------------------------------------- KAS balance--------------------------------------

// let rpc = new Rpc()

// await rpc.connect()

// let address = "kaspatest:*******"

// let balance = await rpc.getBalance(address)

// console.log("balance:", balance)

//   -------------------------------------- transfer KAS --------------------------------------

// let rpc = new Rpc()

// await rpc.connect()

// let privateKey = "****"

// let address = "kaspatest:****"

// let amount = "1"

// let txhash = await rpc.transfer(privateKey, address, amount)

// console.log("txhash;",txhash)

//   -------------------------------------- mint --------------------------------------

let privateKey = "*****"

let krc20 = new KRC20()

await krc20.connect()

var mintdata = {

    p: "krc-20",

    op: 'mint',

    tick: "****"

}

let txid = await krc20.mint(privateKey, mintdata)

console.log("txsh", txid)

// -------------------------------------- transfer --------------------------------------

// let krc20 = new KRC20()

// let privateKey = "****"

// await krc20.connect()

// var transferdata = {

//     p: "krc-20",

//     op: 'transfer',

//     tick: "SNOWDN",

//     to: "kaspatest:****",

//     amt: "1000000000",

// }

// let txid = await krc20.transfer(privateKey, transferdata)

// console.log("txsh", txid)

// -------------------------------------- deploy --------------------------------------

// let krc20 = new KRC20()

// await krc20.connect()

// var deploydata = {

//     p: "krc-20",

//     op: 'deploy',

//     tick: "JEMES1",

//     to: "kaspatest:*****",

//     amt: "1000000000",

//     max: "1000000000000000",

//     lim: "1000000000",

//     dec: "8",

//     pre: "1000000000000000",

// }

// let txid = await krc20.deploy(privateKey, deploydata)

// console.log("txsh", txid)

process.exit(1);


原文链接:https://blog.csdn.net/ERIC_TWELL/article/details/143364683



感动 同情 无聊 愤怒 搞笑 难过 高兴 路过
【字体: 】【收藏】【打印文章】 【 打赏 】 【查看评论

相关文章

    没有相关内容