Skip to content

Commit

Permalink
feat: upgrade freighter-api to 1.5.0 & soroban-client to 0.8.1 (#708)
Browse files Browse the repository at this point in the history
-  feat: upgrade Freighter; fix "view" calls

- if the transaction only needs to be simulated, then the user doesn't
  need to have Freighter connected. This now uses a default/dummy
  account for such calls, but throws an error if the app author tries to
  `signAndSend` such calls.

- use the new methods from `freighter-api@1.5.0` to avoid popping
  pop-ups over and over every time a view call is invoked

- this version correctly pins the stellar-base version, so we can remove
that from the explicit list of dependencies
  • Loading branch information
chadoh authored Jun 19, 2023
1 parent 5ac40db commit 9f045c0
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 30 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ install: install_rust build-libpreflight
build_rust: Cargo.lock
cargo build

# regenerate the example lib in `cmd/crates/soroban-spec-typsecript/fixtures/ts`
build-snapshot:
cargo test --package soroban-spec-typescript --lib -- boilerplate::test::build_package --exact --nocapture --ignored

Expand Down
9 changes: 4 additions & 5 deletions cmd/crates/soroban-spec-typescript/fixtures/ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
"version": "0.0.0",
"name": "contract-data-example",
"dependencies": {
"@stellar/freighter-api": "1.4.0",
"@stellar/freighter-api": "1.5.0",
"buffer": "6.0.3",
"soroban-client": "0.8.0",
"bigint-conversion": "2.4.1",
"stellar-base": "9.0.0-soroban.3"
"soroban-client": "0.8.1",
"bigint-conversion": "2.4.1"
},
"scripts": {
"build": "node ./scripts/build.mjs"
Expand All @@ -19,4 +18,4 @@
"devDependencies": {
"typescript": "5.0.4"
}
}
}
26 changes: 16 additions & 10 deletions cmd/crates/soroban-spec-typescript/fixtures/ts/src/invoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import freighter from "@stellar/freighter-api";
// working around ESM compatibility issues
const {
isConnected,
getPublicKey,
isAllowed,
getUserInfo,
signTransaction,
} = freighter;
import * as SorobanClient from 'soroban-client'
Expand All @@ -25,17 +26,15 @@ export type InvokeArgs = {

/**
* Get account details from the Soroban network for the publicKey currently
* selected in Freighter. If not connected to Freighter, throws errors. Will
* pop up Freighter's modal to request user permissions, if this hasn't been
* done already.
* selected in Freighter. If not connected to Freighter, return null.
*/
export async function getAccount(): Promise<Account> {
if (!await isConnected()) {
throw new Error('Freighter not connected')
async function getAccount(): Promise<Account | null> {
if (!await isConnected() || !await isAllowed()) {
return null
}
const publicKey = await getPublicKey()
const { publicKey } = await getUserInfo()
if (!publicKey) {
throw new Error('Freighter not initialized')
return null
}
return await Server.getAccount(publicKey)
}
Expand All @@ -54,7 +53,10 @@ export class NotImplementedError extends Error { }
* @returns The transaction response, or the simulation result if signing isn't required.
*/
export async function invoke({ method, args = [], fee = 100, signAndSend = false }: InvokeArgs): Promise<(TxResponse & { xdr: string }) | Simulation> {
const account = await getAccount()
const freighterAccount = await getAccount()

// use a placeholder account if not yet connected to Freighter so that view calls can still work
const account = freighterAccount ?? new SorobanClient.Account('GBZXP4PWQLOTBL3P6OE6DQ7QXNYDAZMWQG27V7ATM7P3TKSRDLQS4V7Q', '0')

const contract = new SorobanClient.Contract(CONTRACT_ID)

Expand All @@ -79,6 +81,10 @@ export async function invoke({ method, args = [], fee = 100, signAndSend = false
return results[0]
}

if (!freighterAccount) {
throw new Error('Not connected to Freighter')
}

// is it possible for `auths` to be present but empty? Probably not, but let's be safe.
const auths = simulated.results?.[0]?.auth
let auth_len = auths?.length ?? 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
"version": "0.0.0",
"name": "INSERT_CONTRACT_NAME_HERE",
"dependencies": {
"@stellar/freighter-api": "1.4.0",
"@stellar/freighter-api": "1.5.0",
"buffer": "6.0.3",
"soroban-client": "0.8.0",
"bigint-conversion": "2.4.1",
"stellar-base": "9.0.0-soroban.3"
"soroban-client": "0.8.1",
"bigint-conversion": "2.4.1"
},
"scripts": {
"build": "node ./scripts/build.mjs"
Expand All @@ -19,4 +18,4 @@
"devDependencies": {
"typescript": "5.0.4"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import freighter from "@stellar/freighter-api";
// working around ESM compatibility issues
const {
isConnected,
getPublicKey,
isAllowed,
getUserInfo,
signTransaction,
} = freighter;
import * as SorobanClient from 'soroban-client'
Expand All @@ -25,17 +26,15 @@ export type InvokeArgs = {

/**
* Get account details from the Soroban network for the publicKey currently
* selected in Freighter. If not connected to Freighter, throws errors. Will
* pop up Freighter's modal to request user permissions, if this hasn't been
* done already.
* selected in Freighter. If not connected to Freighter, return null.
*/
export async function getAccount(): Promise<Account> {
if (!await isConnected()) {
throw new Error('Freighter not connected')
async function getAccount(): Promise<Account | null> {
if (!await isConnected() || !await isAllowed()) {
return null
}
const publicKey = await getPublicKey()
const { publicKey } = await getUserInfo()
if (!publicKey) {
throw new Error('Freighter not initialized')
return null
}
return await Server.getAccount(publicKey)
}
Expand All @@ -54,7 +53,10 @@ export class NotImplementedError extends Error { }
* @returns The transaction response, or the simulation result if signing isn't required.
*/
export async function invoke({ method, args = [], fee = 100, signAndSend = false }: InvokeArgs): Promise<(TxResponse & { xdr: string }) | Simulation> {
const account = await getAccount()
const freighterAccount = await getAccount()

// use a placeholder account if not yet connected to Freighter so that view calls can still work
const account = freighterAccount ?? new SorobanClient.Account('GBZXP4PWQLOTBL3P6OE6DQ7QXNYDAZMWQG27V7ATM7P3TKSRDLQS4V7Q', '0')

const contract = new SorobanClient.Contract(CONTRACT_ID)

Expand All @@ -79,6 +81,10 @@ export async function invoke({ method, args = [], fee = 100, signAndSend = false
return results[0]
}

if (!freighterAccount) {
throw new Error('Not connected to Freighter')
}

// is it possible for `auths` to be present but empty? Probably not, but let's be safe.
const auths = simulated.results?.[0]?.auth
let auth_len = auths?.length ?? 0;
Expand Down

0 comments on commit 9f045c0

Please sign in to comment.