diff --git a/apps/walletd/config/providers.tsx b/apps/walletd/config/providers.tsx
index 46c37e9a4..7cec3aced 100644
--- a/apps/walletd/config/providers.tsx
+++ b/apps/walletd/config/providers.tsx
@@ -4,6 +4,7 @@ import { WalletsProvider } from '../contexts/wallets'
import { AddressesProvider } from '../contexts/addresses'
import { EventsProvider } from '../contexts/events'
import { LedgerProvider } from '../contexts/ledger'
+import { AppProvider } from '../contexts/app'
type Props = {
children: React.ReactNode
@@ -11,19 +12,21 @@ type Props = {
export function Providers({ children }: Props) {
return (
-
-
-
-
-
- {/* this is here so that dialogs can use all the other providers,
+
+
+
+
+
+
+ {/* this is here so that dialogs can use all the other providers,
and the other providers can trigger dialogs */}
-
- {children}
-
-
-
-
-
+
+ {children}
+
+
+
+
+
+
)
}
diff --git a/apps/walletd/contexts/app/index.tsx b/apps/walletd/contexts/app/index.tsx
new file mode 100644
index 000000000..a11cd151c
--- /dev/null
+++ b/apps/walletd/contexts/app/index.tsx
@@ -0,0 +1,27 @@
+import { createContext, useContext, useEffect } from 'react'
+import { initSDK } from '@siafoundation/sdk'
+
+function useAppMain() {
+ // Initialize the SDK on app load
+ useEffect(() => {
+ const func = async () => {
+ await initSDK()
+ }
+ func()
+ }, [])
+ return {}
+}
+
+type State = ReturnType
+
+const AppContext = createContext({} as State)
+export const useApp = () => useContext(AppContext)
+
+type Props = {
+ children: React.ReactNode
+}
+
+export function AppProvider({ children }: Props) {
+ const state = useAppMain()
+ return {children}
+}
diff --git a/libs/sdk/src/index.ts b/libs/sdk/src/index.ts
index e59a87889..6ab683a62 100644
--- a/libs/sdk/src/index.ts
+++ b/libs/sdk/src/index.ts
@@ -1,2 +1,3 @@
-export * from './init'
export * from './types'
+export { initSDK } from './init'
+export { getSDK, SDK } from './sdk'
diff --git a/libs/sdk/src/sdk.ts b/libs/sdk/src/sdk.ts
index 948d8a4c6..330af96d7 100644
--- a/libs/sdk/src/sdk.ts
+++ b/libs/sdk/src/sdk.ts
@@ -1,12 +1,22 @@
import { WebTransportClient } from './transport'
-import { WASM } from './types'
+import { WasmApi } from './types'
-export function getSDK() {
+export type SDK = WasmApi & {
+ WebTransportClient: typeof WebTransportClient
+}
+
+export function getWasmApi(): WasmApi {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- const wasm = (global as any).sia as WASM
+ return (globalThis as any).sia as WasmApi
+}
+
+export function getSDK(): SDK {
+ const wasmApi = getWasmApi()
+ if (wasmApi === undefined) {
+ throw new Error('The Sia SDK has not been initialized')
+ }
return {
- rhp: wasm.rhp,
- wallet: wasm.wallet,
+ ...wasmApi,
WebTransportClient,
}
}
diff --git a/libs/sdk/src/transport.ts b/libs/sdk/src/transport.ts
index 372c4e848..c9c1735e5 100644
--- a/libs/sdk/src/transport.ts
+++ b/libs/sdk/src/transport.ts
@@ -1,3 +1,4 @@
+import { getWasmApi } from './sdk'
import {
RPCReadSectorResponse,
RPCSettingsResponse,
@@ -9,26 +10,27 @@ import {
RPCWriteSector,
RPCSettings,
} from './types'
-import { WASM } from './types'
export class WebTransportClient {
#url: string
#cert: string
- #wasm: WASM
#transport!: WebTransport
- constructor(url: string, cert: string, wasm: WASM) {
+ constructor(url: string, cert: string) {
this.#url = url
this.#cert = cert
- this.#wasm = wasm
- }
- async connect() {
+ if (!getWasmApi()) {
+ throw new Error('The Sia SDK has not been initialized.')
+ }
+
if (!('WebTransport' in window)) {
throw new Error('WebTransport is not supported in your browser.')
}
+ }
+ async connect() {
try {
this.#transport = new WebTransport(this.#url, {
serverCertificateHashes: this.#cert
@@ -101,8 +103,8 @@ export class WebTransportClient {
): Promise {
return this.sendRequest(
readSector,
- this.#wasm.rhp.encodeReadSectorRequest,
- this.#wasm.rhp.decodeReadSectorResponse
+ getWasmApi().rhp.encodeReadSectorRequest,
+ getWasmApi().rhp.decodeReadSectorResponse
)
}
@@ -111,16 +113,16 @@ export class WebTransportClient {
): Promise {
return this.sendRequest(
writeSector,
- this.#wasm.rhp.encodeWriteSectorRequest,
- this.#wasm.rhp.decodeWriteSectorResponse
+ getWasmApi().rhp.encodeWriteSectorRequest,
+ getWasmApi().rhp.decodeWriteSectorResponse
)
}
async sendRPCSettingsRequest(): Promise {
return this.sendRequest(
undefined,
- this.#wasm.rhp.encodeSettingsRequest,
- this.#wasm.rhp.decodeSettingsResponse
+ getWasmApi().rhp.encodeSettingsRequest,
+ getWasmApi().rhp.decodeSettingsResponse
)
}
}
diff --git a/libs/sdk/src/types.ts b/libs/sdk/src/types.ts
index 8d3458dc4..1008727aa 100644
--- a/libs/sdk/src/types.ts
+++ b/libs/sdk/src/types.ts
@@ -3,15 +3,14 @@ import {
UnlockConditions,
ConsensusNetwork,
ConsensusState,
+ Currency,
+ Signature,
+ Address,
+ Hash256,
+ PublicKey,
+ PrivateKey,
} from '@siafoundation/types'
-type Currency = string
-type Signature = string
-type Address = string
-type Hash256 = string // 32 bytes
-type PrivateKey = string
-type PublicKey = string // 32 bytes
-
type AccountToken = {
account: PublicKey
validUntil: string
@@ -92,7 +91,7 @@ export type RPCWriteSector = {
export type RPC = RPCSettings | RPCReadSector | RPCWriteSector
-export type WASM = {
+export type WasmApi = {
rhp: {
generateAccount: () => {
privateKey?: PrivateKey
@@ -189,7 +188,7 @@ export type WASM = {
encodedTransaction?: string
error?: string
}
- signTransaction: (
+ signTransactionV1: (
cs: ConsensusState,
cn: ConsensusNetwork,
txn: Transaction,
diff --git a/libs/sdk/src/wasm.ts b/libs/sdk/src/wasm.ts
index d257acab8..f004fe447 100644
--- a/libs/sdk/src/wasm.ts
+++ b/libs/sdk/src/wasm.ts
@@ -5,7 +5,7 @@ export async function initWASM(): Promise {
try {
const go = new window.Go()
const source = await wasm(go.importObject)
- await go.run(source.instance)
+ go.run(source.instance)
} catch (e) {
throw new Error(`failed to initialize WASM: ${(e as Error).message}`)
}
diff --git a/libs/types/src/core.ts b/libs/types/src/core.ts
index aff0d7e63..3a297a5bb 100644
--- a/libs/types/src/core.ts
+++ b/libs/types/src/core.ts
@@ -8,6 +8,7 @@ export type OutputID = string
export type EncryptionKey = string
export type FileContractID = string
export type PublicKey = string
+export type PrivateKey = string
export type TransactionID = Hash256
export type SiacoinOutputID = Hash256
export type SiafundOutputID = Hash256
diff --git a/sdk/main.go b/sdk/main.go
index 8759cce1e..5ebf343d3 100644
--- a/sdk/main.go
+++ b/sdk/main.go
@@ -34,7 +34,7 @@ func main() {
"addressFromSpendPolicy": jsFunc(addressFromSpendPolicy),
"encodeTransaction": jsFunc(encodeTransaction),
"transactionId": jsFunc(transactionID),
- "signTransaction": jsFunc(signTransaction),
+ "signTransactionV1": jsFunc(signTransactionV1),
},
})
c := make(chan bool, 1)
diff --git a/sdk/wallet.go b/sdk/wallet.go
index 1d9cb04a4..0f9ad4611 100644
--- a/sdk/wallet.go
+++ b/sdk/wallet.go
@@ -3,6 +3,7 @@ package main
import (
"bytes"
"crypto/ed25519"
+ "encoding/base64"
"encoding/hex"
"fmt"
"syscall/js"
@@ -146,7 +147,7 @@ func encodeTransaction(this js.Value, args []js.Value) result {
}
// SignTransaction returns the signature of a transaction.
-func signTransaction(this js.Value, args []js.Value) result {
+func signTransactionV1(this js.Value, args []js.Value) result {
if err := checkArgs(args, js.TypeObject, js.TypeObject, js.TypeObject, js.TypeNumber, js.TypeString); err != nil {
return resultErr(err)
}
@@ -187,8 +188,9 @@ func signTransaction(this js.Value, args []js.Value) result {
} else {
sigHash = cs.PartialSigHash(txn, tsig.CoveredFields)
}
+ sig := privateKey.SignHash(sigHash)
return result(map[string]any{
- "signature": privateKey.SignHash(sigHash).String(),
+ "signature": base64.StdEncoding.EncodeToString(sig[:]),
})
}