共计 4377 个字符,预计需要花费 11 分钟才能阅读完成。
Develop WebApps with Vue using Polkadot.js
Element
个别的,以下三个因素会呈现在任何程序上的一次操作中
- 发 / 收信方:Account 钱包地址
- 通道:WebSocket 长连贯
- 信息:Message 可被加密
Account
依赖:
@polkadot/util-crypto
用于生成随机的密钥@polkadot/keyring
用于治理钱包账户,/testing
能够同步开发测试账户@vue-polkadot/vue-settings
同步链节点的根本信息(比方转账时要用到的货币单位)@vue-polkadot/vue-identicon
用于显示账户头像@polkadot/util
一些工具,例如数据格式化
装置 keyring
// store.ts | |
import {cryptoWaitReady} from '@polkadot/util-crypto' | |
import testKeyring from '@polkadot/keyring/testing' | |
const myKeyring = async (store: any) => {await cryptoWaitReady() | |
const keyring = testKeyring({type: 'sr25519'}) | |
Vue.prototype.$keyring = keyring | |
} |
在组件中调用 keyring 生成钱包账户
// Account.vue | |
import {Vue} from 'vue-property-decorator' | |
export default class Account extends Vue { | |
public newAccount: any = { | |
name: '', | |
mnemonicSeed: '', | |
address: '', | |
password: '' | |
} | |
private getAddressFromSeed(mnemonicSeed: string): any { | |
return this.$keyring.createFromUri(mnemonicSeed.trim(), | |
this.getMeta(), | |
'sr25519' | |
) | |
} | |
private getMeta(): any { | |
return { | |
name: this.newAccount?.name || '', | |
whereCreated: 'Earth', | |
whenCreated: Date.now()} | |
} | |
} |
creat 接口用于创立账户,add 接口用于在本地内存里增加账户。
const json = pair.toJson(password) | |
this.$keyring.addFromJson(json) |
交易转账时,金额数据须要额定解决
static sendBalance( | |
sender: string | any, | |
recipient: string, | |
amount: number, | |
tokenDecimals: number | |
): Promise<any> {let value = numberToHex(amount * 1e3 * 10 ** (tokenDecimals || 12)) | |
return exec(sender, 'balances', 'transfer', [recipient, value]) | |
} |
Link to Chain
将 web 客户端与链侧利用建设 websocket 长连贯,以放弃数据通信,随后将 polkdot-api 实例化。
执行的机会个别只需一次,产生在页面加载后。
- connect with websocket
- make the api global
Code
// 引入依赖 | |
import {ApiPromise, WsProvider} from '@polkadot/api' | |
import {EventEmitter} from 'events' | |
// 定义接口类型 | |
export interface ApiService {connect(apiUrl: string, types: any): Promise<ApiPromise | Error> | |
disconnect(): void | |
// registerCustomTypes(userTypes: string, apiUrl?: string): Promise<ApiPromise | Error>; | |
} | |
/** | |
* Singleton instance for @polkadot/api. | |
*/ | |
export default class Api extends EventEmitter implements ApiService {private static _instance: Api = new Api() | |
private _api!: ApiPromise | |
private _apiUrl!: string | |
/** | |
* getInstance | |
* @returns Api Instance | |
*/ | |
public static getInstance(): Api {return Api._instance} | |
private constructor() {super() | |
} | |
/** | |
* connect | |
* @requires apiUrl: string | |
* @returns instance of polkadot-js/api instance | |
*/ | |
public async connect( | |
apiUrl: string, | |
types: Record<any, any> | |
): Promise<ApiPromise | Error> {if (!apiUrl) { | |
throw new TypeError(`[VUE API] ERR: Unable to init api with apiUrl ${apiUrl}` | |
) | |
} | |
try {const provider = new WsProvider(apiUrl) | |
const apiPromise = await ApiPromise.create({provider, types}) | |
this.setApi(apiPromise) | |
this._emit('connect', apiPromise) | |
// const isReady = apiPromise.isReady.then(api => {// this.setApi(apiPromise) | |
// this._emit('connect', apiPromise) | |
// }) | |
} catch (err) {this._emit('error', err) | |
throw err | |
} | |
this.setUrl(apiUrl) | |
return this._api | |
} | |
/** | |
* disconnect | |
*/ | |
public disconnect(): void {if (this._api) {// this._api.once('disconnected', () => this._emit('disconnect', this._apiUrl)); | |
this._api.disconnect() | |
this.setUrl('') | |
} | |
} | |
private setApi(api: ApiPromise) {this._api = api} | |
private setUrl(apiUrl: string) {this._apiUrl = apiUrl} | |
get api(): ApiPromise {return this._api} | |
/** | |
* tryEmit | |
* | |
*/ | |
public _emit(message = 'event', payload?: ApiPromise | Error): void {this.emit(message, payload) | |
} | |
} |
Tips:
websocket
连贯失败的异样无奈捕捉,暂不思考解决。event
依赖次要解决 connect 事件的胜利 / 失败监听,若果在内部已有其余的异样捕捉机制则能够去掉此处。@vue-polkadot/vue-api
插件和此代码性能统一,前者有些针对 vue 的封装。@vue-polkadot/vue-api
在实例化时没有传入 type 参数,如果有自定义 type 须要传入的要另做解决。
Query & Transactions
Query
import Connector from '@/api/util/connector' | |
static async getBalance(address: string): Promise<any> {let { api} = Connector.getInstance() | |
const {data: balance} = await api.query.system.account(address) | |
return balance.free | |
} |
Transactions
import Connector from '@/api/util/connector' | |
let {api} = Connector.getInstance() | |
const transfer = await api.tx[section][method](...params) | |
/*unsub 将执行继续的监听。返回的回调函数能够在出块或确认块后进行监听。*/ | |
const unsub = await transfer.signAndSend( | |
sender, // account: AddressOrPair, | |
{}, //options: Partial<SignerOptions> | |
()=>{ //statusCb | |
// after isFinalized | |
unsub()} | |
) |
Transactions with Extension
import Connector from '@/lib/substrate/Api' | |
import { | |
web3Accounts, | |
web3Enable, | |
web3FromAddress | |
} from '@polkadot/extension-dapp' | |
let {api} = Connector.getInstance() | |
const allInjected = await web3Enable('Dipole') | |
const allAccounts = await web3Accounts() | |
// finds an injector for an address | |
const sender = allAccounts[0].address | |
const injector = await web3FromAddress(sender) | |
api.setSigner(injector.signer) |
Transactions with password
if (!sender.isLocked) {await unSubFoo(payload) | |
} else { | |
try { | |
// unlock account success | |
sender.decodePkcs8(password) | |
await unSubFoo(payload) | |
} catch (err){ | |
// unlock password failed | |
console.log(err) | |
} | |
} |
参考
- polkadot.js
- vue-polkadot
- polkadot-js/chromeExtension
- 区块链(BlockChain)中私钥、公钥和钱包地址三者关系
正文完