11import StellarSdk from "stellar-sdk" ;
2+ import * as SorobanClient from "soroban-client" ;
23import { DataProvider } from "@stellar/wallet-sdk" ;
34import {
45 Account ,
@@ -21,6 +22,12 @@ import { getIconUrlFromIssuer } from "./helpers/getIconUrlFromIssuer";
2122import { getDomainFromIssuer } from "./helpers/getDomainFromIssuer" ;
2223import { stellarSdkServer } from "./helpers/stellarSdkServer" ;
2324
25+ import {
26+ decodeAccountIdentifier ,
27+ decodeScVal ,
28+ decodeBytesN ,
29+ } from "./helpers/soroban" ;
30+
2431const TRANSACTIONS_LIMIT = 100 ;
2532
2633export const createAccount = async (
@@ -175,6 +182,7 @@ export const loadAccount = (): Promise<{
175182 applicationState : APPLICATION_STATE ;
176183 allAccounts : Array < Account > ;
177184 bipPath : string ;
185+ tokenIdList : string [ ] ;
178186} > =>
179187 sendMessageToBackground ( {
180188 type : SERVICE_TYPES . LOAD_ACCOUNT ,
@@ -736,3 +744,124 @@ export const getBlockedDomains = async () => {
736744 } ) ;
737745 return resp ;
738746} ;
747+
748+ type TxToOp = {
749+ [ index : string ] : {
750+ tx : SorobanClient . Transaction <
751+ SorobanClient . Memo < SorobanClient . MemoType > ,
752+ SorobanClient . Operation [ ]
753+ > ;
754+ decoder : ( val : Buffer ) => string | number ;
755+ } ;
756+ } ;
757+
758+ interface SorobanTokenRecord {
759+ [ key : string ] : unknown ;
760+ balance : number ;
761+ name : string ;
762+ symbol : string ;
763+ decimals : string ;
764+ }
765+
766+ export const getSorobanTokenBalance = async (
767+ server : SorobanClient . Server ,
768+ contractId : string ,
769+ txBuilders : {
770+ // need a builder per operation until multi-op transactions are released
771+ balance : SorobanClient . TransactionBuilder ;
772+ name : SorobanClient . TransactionBuilder ;
773+ decimals : SorobanClient . TransactionBuilder ;
774+ symbol : SorobanClient . TransactionBuilder ;
775+ } ,
776+ params : SorobanClient . xdr . ScVal [ ] ,
777+ ) => {
778+ const contract = new SorobanClient . Contract ( contractId ) ;
779+
780+ // Right now we can only have 1 operation per TX in Soroban
781+ // There is ongoing work to lift this restriction
782+ // but for now we need to do 4 txs to show 1 user balance. :(
783+ const balanceTx = txBuilders . balance
784+ . addOperation ( contract . call ( "balance" , ...params ) )
785+ . setTimeout ( SorobanClient . TimeoutInfinite )
786+ . build ( ) ;
787+
788+ const nameTx = txBuilders . name
789+ . addOperation ( contract . call ( "name" ) )
790+ . setTimeout ( SorobanClient . TimeoutInfinite )
791+ . build ( ) ;
792+
793+ const symbolTx = txBuilders . symbol
794+ . addOperation ( contract . call ( "symbol" ) )
795+ . setTimeout ( SorobanClient . TimeoutInfinite )
796+ . build ( ) ;
797+
798+ const decimalsTx = txBuilders . decimals
799+ . addOperation ( contract . call ( "decimals" ) )
800+ . setTimeout ( SorobanClient . TimeoutInfinite )
801+ . build ( ) ;
802+
803+ const txs : TxToOp = {
804+ balance : {
805+ tx : balanceTx ,
806+ decoder : decodeAccountIdentifier ,
807+ } ,
808+ name : {
809+ tx : nameTx ,
810+ decoder : decodeBytesN ,
811+ } ,
812+ symbol : {
813+ tx : symbolTx ,
814+ decoder : decodeBytesN ,
815+ } ,
816+ decimals : {
817+ tx : decimalsTx ,
818+ decoder : decodeScVal ,
819+ } ,
820+ } ;
821+
822+ const tokenBalanceInfo = Object . keys ( txs ) . reduce ( async ( prev , curr ) => {
823+ const _prev = await prev ;
824+ const { tx, decoder } = txs [ curr ] ;
825+ const { results } = await server . simulateTransaction ( tx ) ;
826+ if ( ! results || results . length !== 1 ) {
827+ throw new Error ( "Invalid response from simulateTransaction" ) ;
828+ }
829+ const result = results [ 0 ] ;
830+ _prev [ curr ] = decoder ( Buffer . from ( result . xdr , "base64" ) ) ;
831+
832+ return _prev ;
833+ } , Promise . resolve ( { } as SorobanTokenRecord ) ) ;
834+
835+ return tokenBalanceInfo ;
836+ } ;
837+
838+ export const addTokenId = async (
839+ tokenId : string ,
840+ ) : Promise < {
841+ tokenIdList : string [ ] ;
842+ } > => {
843+ let error = "" ;
844+ let tokenIdList = [ ] as string [ ] ;
845+
846+ try {
847+ ( { tokenIdList, error } = await sendMessageToBackground ( {
848+ tokenId,
849+ type : SERVICE_TYPES . ADD_TOKEN_ID ,
850+ } ) ) ;
851+ } catch ( e ) {
852+ console . error ( e ) ;
853+ }
854+
855+ if ( error ) {
856+ throw new Error ( error ) ;
857+ }
858+
859+ return { tokenIdList } ;
860+ } ;
861+
862+ export const getTokenIds = async ( ) : Promise < string [ ] > => {
863+ const resp = await sendMessageToBackground ( {
864+ type : SERVICE_TYPES . GET_TOKEN_IDS ,
865+ } ) ;
866+ return resp . tokenIdList ;
867+ } ;
0 commit comments