Kaspa钱包ts代码封装

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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值