UNPKG

@ledgerhq/hw-app-starknet

Version:

Ledger Hardware Wallet Starknet Application API

2 lines (1 loc) 9.65 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./helper.cjs"),r=require("./common.cjs"),B=require("starknet"),U=require("./node_modules/@starknet-io/types-js/dist/esm/api/constants.cjs");function v(f){let a=f.replace(/^0x0*/,"");if(a.length>r.HASH_MAX_LENGTH)throw"invalid hash length";return a="0".repeat(1+r.HASH_MAX_LENGTH-a.length).concat(a),a}function D(f){const a=[];for(let e=0;e<f.length;e+=2)a.push(parseInt(f.substring(e,e+2),16));return Uint8Array.from(a)}class m{transport;constructor(a){if(this.transport=a,!a)throw new Error("Transport has not been defined")}async sendApdu(a=r.INS.GET_VERSION,e=0,o=0,s=new Uint8Array(0)){return this.transport.send(r.CLA,a,e,o,Buffer.from(s),[r.LedgerError.NoError,r.LedgerError.BadCla,r.LedgerError.BadIns,r.LedgerError.InvalidP1P2,r.LedgerError.UserRejected]).then(n=>{const _=n.subarray(-2),N=_[0]*256+_[1];let h=r.errorCodeToString(N);return{data:n.subarray(0,-2),returnCode:N,errorMessage:h}})}async getAppVersion(){const a=await this.sendApdu(r.INS.GET_VERSION);return{returnCode:a.returnCode,errorMessage:a.errorMessage,major:a.data[0],minor:a.data[1],patch:a.data[2]}}async getPubKey(a,e=!0){const o=t.serializePath(a);try{const s=await this.sendApdu(r.INS.GET_PUB_KEY,e?1:0,0,o);return{publicKey:s.data.slice(1,65),returnCode:s.returnCode,errorMessage:s.errorMessage}}catch{return console.warn("Caught error"),{publicKey:new Uint8Array(0),returnCode:r.LedgerError.ExecutionError,errorMessage:r.errorCodeToString(r.LedgerError.ExecutionError)}}}async getStarkKey(a,e=!0){const{publicKey:o,errorMessage:s,returnCode:n}=await this.getPubKey(a,e);return n!==r.LedgerError.NoError?{starkKey:o,returnCode:n,errorMessage:s}:{starkKey:o.slice(0,32),returnCode:n,errorMessage:s}}async signHash(a,e){const o=t.serializePath(a),s=D(v(e));try{let n=await this.sendApdu(r.INS.SIGN_HASH,0,0,o);return n=await this.sendApdu(r.INS.SIGN_HASH,1,0,s),n.returnCode!==r.LedgerError.NoError?{returnCode:n.returnCode,errorMessage:r.errorCodeToString(n.returnCode),r:new Uint8Array(0),s:new Uint8Array(0),v:0}:{returnCode:n.returnCode,errorMessage:n.errorMessage,r:n.data.subarray(1,33),s:n.data.subarray(33,65),v:n.data[65]}}catch{return{returnCode:r.LedgerError.ExecutionError,errorMessage:r.errorCodeToString(r.LedgerError.ExecutionError),r:new Uint8Array(0),s:new Uint8Array(0),v:0}}}async signTx(a,e,o){await this.sendApdu(r.INS.SIGN_TX,0,0,t.serializePath(a));const s=t.toBN(o.accountAddress),n=t.toBN(o.chainId),_=t.toBN(o.nonce),N=t.toBN(this.encodeDataAvailabilityMode(o.nonceDataAvailabilityMode,o.feeDataAvailabilityMode));let h=new Uint8Array([...s.toArray("be",32),...n.toArray("be",32),..._.toArray("be",32),...N.toArray("be",32)]);await this.sendApdu(r.INS.SIGN_TX,1,0,h);const y=t.toBN(o.tip),{l1_gas:l,l2_gas:u,l1_data_gas:S}=this.encodeResourceBounds(o.resourceBounds);h=new Uint8Array([...y.toArray("be",32),...l.toArray("be",32),...u.toArray("be",32),...S.toArray("be",32)]),await this.sendApdu(r.INS.SIGN_TX,2,0,h),await this.sendApdu(r.INS.SIGN_TX,3,0,new Uint8Array(0)),await this.sendApdu(r.INS.SIGN_TX,4,0,new Uint8Array(0));let E=t.toBN(e.length);h=new Uint8Array([...E.toArray("be",32)]),await this.sendApdu(r.INS.SIGN_TX,5,0,h);let i,c={returnCode:r.LedgerError.ExecutionError,errorMessage:"Execution Error",h:new Uint8Array(0),r:new Uint8Array(0),s:new Uint8Array(0),v:0};for(const b of e){const p=B.CallData.toCalldata(b.calldata);let g=new Uint8Array((3+p.length)*32);t.toBN(b.contractAddress).toArray("be",32).forEach((A,w)=>g[w]=A),t.toBN(B.hash.getSelectorFromName(b.entrypoint)).toArray("be",32).forEach((A,w)=>g[32+w]=A),t.toBN(p.length).toArray("be",32).forEach((A,w)=>g[64+w]=A),p.forEach((A,w)=>{t.toBN(A).toArray("be",32).forEach((T,M)=>g[96+32*w+M]=T)});let C=[];for(let A=0;A<g.length;A+=224)C.push(g.slice(A,A+224));if(C.length>1){if(i=await this.sendApdu(r.INS.SIGN_TX,6,0,C[0]),i.returnCode!==r.LedgerError.NoError)return c;for(const A of C.slice(1))if(i=await this.sendApdu(r.INS.SIGN_TX,6,1,A),i.returnCode!==r.LedgerError.NoError)return c}else if(i=await this.sendApdu(r.INS.SIGN_TX,6,0,C[0]),i.returnCode!==r.LedgerError.NoError)return c}return i?.returnCode===r.LedgerError.NoError?{returnCode:i.returnCode,errorMessage:i.errorMessage,h:i.data.subarray(0,32),r:i.data.subarray(33,65),s:i.data.subarray(65,97),v:i.data[97]}:c}async signTxV1(a,e,o){await this.sendApdu(r.INS.SIGN_TX_V1,0,0,t.serializePath(a));const s=t.toBN(o.accountAddress),n=t.toBN(o.max_fee),_=t.toBN(o.chainId),N=t.toBN(o.nonce);let h=new Uint8Array([...s.toArray("be",32),...n.toArray("be",32),..._.toArray("be",32),...N.toArray("be",32)]);await this.sendApdu(r.INS.SIGN_TX_V1,1,0,h);let y=t.toBN(e.length);h=new Uint8Array([...y.toArray("be",32)]),await this.sendApdu(r.INS.SIGN_TX_V1,2,0,h);let l,u={returnCode:r.LedgerError.ExecutionError,errorMessage:"Execution Error",h:new Uint8Array(0),r:new Uint8Array(0),s:new Uint8Array(0),v:0};for(const S of e){const E=B.CallData.toCalldata(S.calldata);let i=new Uint8Array((3+E.length)*32);t.toBN(S.contractAddress).toArray("be",32).forEach((d,I)=>i[I]=d),t.toBN(B.hash.getSelectorFromName(S.entrypoint)).toArray("be",32).forEach((d,I)=>i[32+I]=d),t.toBN(E.length).toArray("be",32).forEach((d,I)=>i[64+I]=d),E.forEach((d,I)=>{t.toBN(d).toArray("be",32).forEach((C,A)=>i[96+32*I+A]=C)});let g=[];for(let d=0;d<i.length;d+=224)g.push(i.slice(d,d+224));if(g.length>1){if(l=await this.sendApdu(r.INS.SIGN_TX_V1,3,0,g[0]),l.returnCode!==r.LedgerError.NoError)return u;for(const d of g.slice(1))if(l=await this.sendApdu(r.INS.SIGN_TX_V1,3,1,d),l.returnCode!==r.LedgerError.NoError)return u}else if(l=await this.sendApdu(r.INS.SIGN_TX_V1,3,0,g[0]),l.returnCode!==r.LedgerError.NoError)return u}return l?.returnCode===r.LedgerError.NoError?{returnCode:l.returnCode,errorMessage:l.errorMessage,h:l.data.subarray(0,32),r:l.data.subarray(33,65),s:l.data.subarray(65,97),v:l.data[97]}:u}async signDeployAccount(a,e){await this.sendApdu(r.INS.DEPLOY_ACCOUNT,0,0,t.serializePath(a));const o=t.toBN(e.contractAddress),s=t.toBN(e.chainId),n=t.toBN(e.nonce),_=t.toBN(this.encodeDataAvailabilityMode(e.nonceDataAvailabilityMode,e.feeDataAvailabilityMode)),N=t.toBN(e.class_hash),h=t.toBN(e.contract_address_salt);let y=new Uint8Array([...o.toArray("be",32),...s.toArray("be",32),...n.toArray("be",32),..._.toArray("be",32),...N.toArray("be",32),...h.toArray("be",32)]);await this.sendApdu(r.INS.DEPLOY_ACCOUNT,1,0,y);const l=t.toBN(e.tip),{l1_gas:u,l2_gas:S,l1_data_gas:E}=this.encodeResourceBounds(e.resourceBounds);y=new Uint8Array([...l.toArray("be",32),...u.toArray("be",32),...S.toArray("be",32),...E.toArray("be",32)]),await this.sendApdu(r.INS.DEPLOY_ACCOUNT,2,0,y),await this.sendApdu(r.INS.DEPLOY_ACCOUNT,3,0,new Uint8Array(0));let i=t.toBN(e.constructor_calldata.length);y=new Uint8Array([...i.toArray("be",32)]),await this.sendApdu(r.INS.DEPLOY_ACCOUNT,4,0,y);let c,b={returnCode:r.LedgerError.ExecutionError,errorMessage:"Execution Error",h:new Uint8Array(0),r:new Uint8Array(0),s:new Uint8Array(0),v:0},p=new Uint8Array(e.constructor_calldata.length*32);e.constructor_calldata.forEach((d,I)=>{t.toBN(d).toArray("be",32).forEach((C,A)=>p[32*I+A]=C)});let g=[];for(let d=0;d<p.length;d+=224)g.push(p.slice(d,d+224));for(const d of g)if(c=await this.sendApdu(r.INS.DEPLOY_ACCOUNT,5,0,d),c.returnCode!==r.LedgerError.NoError)return b;return c?.returnCode===r.LedgerError.NoError?{returnCode:c.returnCode,errorMessage:c.errorMessage,h:c.data.subarray(0,32),r:c.data.subarray(33,65),s:c.data.subarray(65,97),v:c.data[97]}:b}async signDeployAccountV1(a,e){await this.sendApdu(r.INS.DEPLOY_ACCOUNT_V1,0,0,t.serializePath(a));const o=t.toBN(e.contractAddress),s=t.toBN(e.class_hash),n=t.toBN(e.contract_address_salt),_=t.toBN(e.max_fee),N=t.toBN(e.chainId),h=t.toBN(e.nonce);let y=new Uint8Array([...o.toArray("be",32),...s.toArray("be",32),...n.toArray("be",32),..._.toArray("be",32),...N.toArray("be",32),...h.toArray("be",32)]);await this.sendApdu(r.INS.DEPLOY_ACCOUNT_V1,1,0,y);let l=t.toBN(e.constructor_calldata.length);y=new Uint8Array([...l.toArray("be",32)]),await this.sendApdu(r.INS.DEPLOY_ACCOUNT_V1,2,0,y);let u,S={returnCode:r.LedgerError.ExecutionError,errorMessage:"Execution Error",h:new Uint8Array(0),r:new Uint8Array(0),s:new Uint8Array(0),v:0},E=new Uint8Array(e.constructor_calldata.length*32);e.constructor_calldata.forEach((c,b)=>{t.toBN(c).toArray("be",32).forEach((g,d)=>E[32*b+d]=g)});let i=[];for(let c=0;c<E.length;c+=224)i.push(E.slice(c,c+224));for(const c of i)if(u=await this.sendApdu(r.INS.DEPLOY_ACCOUNT_V1,3,0,c),u.returnCode!==r.LedgerError.NoError)return S;return u?.returnCode===r.LedgerError.NoError?{returnCode:u.returnCode,errorMessage:u.errorMessage,h:u.data.subarray(0,32),r:u.data.subarray(33,65),s:u.data.subarray(65,97),v:u.data[97]}:S}async signMessage(a,e,o){const s=B.typedData.getMessageHash(e,o);return this.signHash(a,s)}encodeResourceBounds(a){const e=BigInt(64),o=BigInt(128),s=e+o,n=BigInt(B.shortString.encodeShortString("L1_GAS")),_=BigInt(B.shortString.encodeShortString("L2_GAS")),N=BigInt(B.shortString.encodeShortString("L1_DATA")),h=(n<<s)+(BigInt(a.l1_gas.max_amount)<<o)+BigInt(a.l1_gas.max_price_per_unit),y=(_<<s)+(BigInt(a.l2_gas.max_amount)<<o)+BigInt(a.l2_gas.max_price_per_unit),l=(N<<s)+(BigInt(a.l1_data_gas.max_amount)<<o)+BigInt(a.l1_data_gas.max_price_per_unit);return{l1_gas:t.toBN(h),l2_gas:t.toBN(y),l1_data_gas:t.toBN(l)}}encodeDataAvailabilityMode(a,e){const o=BigInt(32),s=a===U.EDataAvailabilityMode.L1?0:1,n=e===U.EDataAvailabilityMode.L1?0:1;return(BigInt(s)<<o)+BigInt(n)}}exports.LedgerError=r.LedgerError;exports.StarknetClient=m;