UNPKG

scrypt-ts

Version:

A toolset for building sCrypt smart contract applications on Bitcoin SV network written in typescript.

243 lines 10.4 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.DotwalletSigner = void 0; const scryptlib_1 = require("scryptlib"); const abstract_signer_1 = require("../abstract-signer"); const utils_1 = require("../utils"); const superagent_1 = __importDefault(require("superagent")); const DAPP_API_PATHS = { dapp_list_unspent: `/v1/grandet_dapp/dapp_list_unspent`, dapp_list_unspent_by_address: `/v1/grandet_dapp/dapp_list_unspent_by_address`, dapp_sign_raw_transaction: `/v1/grandet_dapp/dapp_sign_raw_transaction`, dapp_get_signature: `/v1/grandet_dapp/dapp_get_signature`, dapp_get_balance: `/v1/grandet_dapp/dapp_get_balance`, dapp_send_raw_transaction: `/v1/grandet_dapp/dapp_send_raw_transaction`, dapp_get_raw_change_address: `/v1/grandet_dapp/dapp_get_raw_change_address`, dapp_get_public_key: `/v1/grandet_dapp/dapp_get_public_key`, get_access_token: `/v1/oauth2/get_access_token` }; /** * This option can be used in both development environment and production environment. * See [access-token]{@link https://oauth.net/2/access-tokens} and [DotWallet APIs for authorization]{@link https://developers.dotwallet.com/documents/en/#authorization} to known how to get a access token. */ function handleRes(res) { if (res.ok) { const body = res.body ? res.body : JSON.parse(res.text); const { code, data, msg } = body; if (code === 0) { return data; } else if (code === 75000) { window.localStorage.removeItem('access_token'); } throw new Error(`error response, code = ${code}, msg: ${msg}`); } else { throw new Error(`error response`); } } const API_DOTWALLET = `https://api.ddpurse.com`; /** * a [signer]{@link https://docs.scrypt.io/how-to-test-a-contract#signer } which implemented the protocol with the [dotwallet]{@link https://www.dotwallet.com/en}, * and dapps can use to interact with the dotwallet. */ class DotwalletSigner extends abstract_signer_1.Signer { constructor(accessToken, provider) { super(provider); this.sender = { "appid": "bsv_coin_regular", "user_index": 0 }; this.utxos_public_key = new Map(); this.accessToken = accessToken; } /** * Check if the wallet has been authenticated * @returns {boolean} true | false */ isAuthenticated() { if (this.accessToken) { return Promise.resolve(true); } return Promise.resolve(false); } /** * Request wallet authentication * @returns A promise which resolves to if the wallet has been authenticated and the authenticate error message */ requestAuth() { return __awaiter(this, void 0, void 0, function* () { if (this.accessToken) { yield this.alignProviderNetwork(); return Promise.resolve({ isAuthenticated: true, error: '' }); } return Promise.resolve({ isAuthenticated: false, error: '' }); }); } setProvider(provider) { throw new Error("cannot alter provider"); } getDefaultAddress() { return __awaiter(this, void 0, void 0, function* () { const public_key = yield this.getDefaultPubKey(); return public_key.toAddress(scryptlib_1.bsv.Networks.mainnet); }); } getNetwork() { return __awaiter(this, void 0, void 0, function* () { const address = yield this.getDefaultAddress(); return address.network; }); } getBalance(address) { return __awaiter(this, void 0, void 0, function* () { if (address) { return this.connectedProvider.getBalance(address); } const res = yield superagent_1.default.post(`${API_DOTWALLET}${DAPP_API_PATHS.dapp_get_balance}`) .set('Content-Type', 'application/json') .set('Authorization', `Bearer ${this.accessToken}`) .send({ "sender": this.sender, }); const data = handleRes(res); const { confirm, unconfirm } = data; return { confirmed: confirm, unconfirmed: unconfirm }; }); } getDefaultPubKey() { return __awaiter(this, void 0, void 0, function* () { if (this.default_public_key) { return this.default_public_key; } const res = yield superagent_1.default.post(`${API_DOTWALLET}${DAPP_API_PATHS.dapp_get_public_key}`) .set('Content-Type', 'application/json') .set('Authorization', `Bearer ${this.accessToken}`) .send({ "sender": this.sender, }); const data = handleRes(res); const { public_key } = data; this.default_public_key = scryptlib_1.bsv.PublicKey.fromString(public_key); return this.default_public_key; }); } getPubKey(address) { return __awaiter(this, void 0, void 0, function* () { throw new Error(`Method ${this.constructor.name}#getPubKey not implemented.`); }); } signMessage(message, address) { return __awaiter(this, void 0, void 0, function* () { throw new Error(`Method ${this.constructor.name}#signMessage not implemented.`); }); } getSignatures(rawTxHex, sigRequests) { return __awaiter(this, void 0, void 0, function* () { const network = yield this.getNetwork(); const inputInfos = sigRequests.flatMap((sigReq) => { const addresses = (0, utils_1.parseAddresses)(sigReq.address, network); return addresses.map(address => { let scriptHex = sigReq.scriptHex; if (!scriptHex) { scriptHex = scryptlib_1.bsv.Script.buildPublicKeyHashOut(address).toHex(); } else if (sigReq.csIdx !== undefined) { scriptHex = scryptlib_1.bsv.Script.fromHex(scriptHex).subScript(sigReq.csIdx).toHex(); } return { txHex: rawTxHex, inputIndex: sigReq.inputIndex, scriptHex, satoshis: sigReq.satoshis, sigtype: sigReq.sigHashType || scryptlib_1.DEFAULT_SIGHASH_TYPE, prevTxId: sigReq.prevTxId, outputIndex: sigReq.outputIndex, address: address.toString() }; }); }); return Promise.all(inputInfos.map((inputInfo) => __awaiter(this, void 0, void 0, function* () { const res = yield superagent_1.default.post(`${API_DOTWALLET}${DAPP_API_PATHS.dapp_get_signature}`) .set('Content-Type', 'application/json') .set('Authorization', `Bearer ${this.accessToken}`) .send({ sender: this.sender, input_index: inputInfo.inputIndex, sig_type: inputInfo.sigtype, rawtx: rawTxHex, addr: inputInfo.address, }); const data = handleRes(res); const { hex_signature } = data; let publicKey = this.utxos_public_key.get(`${inputInfo.prevTxId}:${inputInfo.outputIndex}`); if (!publicKey) { publicKey = (0, scryptlib_1.toHex)(this.default_public_key); } return { inputIndex: inputInfo.inputIndex, sig: hex_signature, publicKey: publicKey, sigHashType: inputInfo.sigtype }; }))); }); } /** * Get a list of the P2PKH UTXOs. * @param address The address of the returned UTXOs belongs to. * @param options The optional query conditions, see details in `UtxoQueryOptions`. * @returns A promise which resolves to a list of UTXO for the query options. */ listUnspent(address, options) { return __awaiter(this, void 0, void 0, function* () { const res = yield superagent_1.default.post(`${API_DOTWALLET}${DAPP_API_PATHS.dapp_list_unspent}`) .set('Content-Type', 'application/json') .set('Authorization', `Bearer ${this.accessToken}`) .send({ "sender": this.sender, "min_amount": 0 }); const data = handleRes(res); const utxos = data.utxos.map((utxo) => ({ txId: utxo.tx_hash, outputIndex: utxo.output_index, satoshis: utxo.satoshis, script: utxo.script, address: utxo.addr, pubkey: utxo.pubkey })); utxos.forEach(utxo => { this.utxos_public_key.set(`${utxo.txId}:${utxo.outputIndex}`, utxo['pubkey']); }); if (options) { return (0, utils_1.filterUTXO)(utxos, options); } return utxos; }); } } exports.DotwalletSigner = DotwalletSigner; DotwalletSigner.DEBUG_TAG = "DotwalletSigner"; //# sourceMappingURL=dotwallet-signer.js.map