使用Polkadot.jsElement用Vue开发WebApp一般在任何程序上一次操作都会出现以下三个元素Sender/Receiver:账户钱包地址Channel:WebSocket长连接Information:消息可以是加密账户依赖:@polkadot/util-crypto用于生成随机密钥@polkadot/keyring用于管理钱包账户,/testing可以同步开发测试账户@vue-polkadot/vue-settings同步链节点的基本信息(比如转账时使用的货币单位)@vue-polkadot/vue-identicon用于显示账户头像@polkadot/util一些工具,比如数据格式化和安装keyring//store.tsimport{cryptoWaitReady}来自'@polkadot/util-crypto'从'@polkadot/keyring/testing'constmyKeyring=async(store:any)importtestKeyring=>{awaitcryptoWaitReady()constkeyring=testKeyring({type:'sr25519'})Vue.原型.$keyring=keyring}在组件中调用keyring生成钱包账户//Account.vueimport{Vue}from'vue-property-decorator'exportdefaultclassAccountextendsVue{publicnewAccount:any={name:'',mnemonicSeed:'',地址:'',密码:''}privategetAddressFromSeed(mnemonicSeed:string):any{returnthis.$keyring.createFromUri(mnemonicSeed.trim(),this.getMeta(),'sr25519')}privategetMeta():any{返回{name:this.newAccount?.name||'',whereCreated:'Earth',whenCreated:Date.now()}}}creat接口用于创建账户,add接口用于在本地内存中添加账户constjson=pair.toJson(password)this.$keyring.addFromJson(json)交易转账时,金额数据需要额外处理1e3*10**(tokenDecimals||12))returnexec(sender,'balances','transfer',[recipient,value])}LinktoChain在web客户端和链端应用程序之间建立一个websocket持久连接保持数据通信,然后实例化polkdot-api。执行的时机一般只需要执行一次,发生在页面加载完成之后。connectwithwebsocketmaketheapiglobalCode//引入依赖import{ApiPromise,WsProvider}from'@polkadot/api'import{EventEmitter}from'events'//定义接口类型exportinterfaceApiService{connect(apiUrl:string,types:any):承诺disconnect():void//registerCustomTypes(userTypes:string,apiUrl?:string):Promise;}/***@polkadot/api的单例实例。*/exportdefaultclassApiextendsEventEmitterimplementsApiService{privatestatic_instance:Api=newApi()private_api!:ApiPromiseprivate_apiUrl!:string/***getInstance*@returnsApi实例*/publicstaticgetInstance():Api{returnApi._instance}privateconstructor(){super()}/***connect*@requiresapiUrl:string*@returnsinstanceofpolkadot-js/apiinstance*/publicasyncconnect(apiUrl:string,types:Record<任何,任何>):Promise{if(!apiUrl){thrownewTypeError(`[VUEAPI]ERR:无法使用apiUrl${apiUrl}`初始化api)}try{constprovider=newWsProvider(apiUrl)constapiPromise=awaitApiPromise.create({provider,types})this.setApi(apiPromise)this._emit('connect',apiPromise)//constisReady=apiPromise.isReady.then(api=>{//this.setApi(apiPromise)//this._emit('connect',apiPromise)//})}catch(err){this._emit('error',err)throwerr}this.setUrl(apiUrl)returnthis._api}/***disconnect*/publicdisconnect():void{if(this._api){//this._api.once('disconnected',()=>this._emit('disconnect',this._apiUrl));this._api.disconnect()this.setUrl('')}}privatesetApi(api:ApiPromise){this._api=api}privatesetUrl(apiUrl:string){this._apiUrl=apiUrl}getapi():ApiPromise{returnthis._api}/***tryEmit**/public_emit(message='event',payload?:ApiPromise|Error):void{this.emit(message,payload)}}Tips:websocket连接失败的异常无法被捕获,不会被捕获是否考虑解决事件依赖于主要处理连接事件的成功/失败监控。如果有其他外部异常捕获机制,这个可以去掉。@vue-polkadot/vue-api插件与这段代码功能相同,前者对vue有一些封装。@vue-polkadot/vue-api在实例化的时候没有传入类型参数。如果有自定义类型需要传入,需要单独处理。Query&TransactionsQueryimportConnectorfrom'@/api/util/connector'staticasyncgetBalance(address:string):Promise{let{api}=Connector.getInstance()const{data:balance}=awaitapi.query复制代码.system.account(address)returnbalance.free}TransactionsimportConnectorfrom'@/api/util/connector'let{api}=Connector.getInstance()consttransfer=awaitapi.tx[部分][方法](...params)/*unsub将执行持续监控。返回的回调函数可以在区块产生或确认后停止监听。*/constunsub=awaittransfer.signAndSend(sender,//account:AddressOrPair,{},//options:Partial()=>{//statusCb//isFinalizedunsub()})与ExtensionimportConnector的交易来自'@/lib/substrate/Api'import{web3Accounts,web3Enable,web3FromAddress}来自'@polkadot/extension-dapp'let{api}=Connector.getInstance()constallInjected=awaitweb3Enable('Dipole')constallAccounts=awaitweb3Accounts()//找到地址的注入器constsender=allAccounts[0].addressconstinjector=awaitweb3FromAddress(sender)api.setSigner(injector.signer)Transactionswithpasswordif(!sender.isLocked){awaitunSubFoo(payload)}else{try{//解锁账户成功sender.decodePkcs8(password)awaitunSubFoo(payload)}catch(err){//解锁密码失败console.log(err)}}参考polkadot.jsvue-polkadotpolkadot-js/chromeExtension区块链(BlockChain)中私钥、公钥和钱包地址的关系