Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ Most apps create a wallet client through `OMSClient`. Use this initializer only
### walletAddress

```swift
var walletAddress: String
var walletAddress: String?
```

The read-only on-chain address of the active wallet. Empty until a wallet is restored or activated by `completeEmailAuth`, `useWallet`, or `createWallet`.
The read-only on-chain address of the active wallet, or `nil` until a wallet is restored or activated by `completeEmailAuth`, `useWallet`, or `createWallet`.

### walletId

Expand Down Expand Up @@ -410,7 +410,9 @@ func sendTransaction(
to: String,
value: String,
selectFeeOption: FeeOptionSelector? = nil,
mode: TransactionMode = .relayer
mode: TransactionMode = .relayer,
waitForStatus: Bool = true,
statusPolling: TransactionStatusPollingOptions = TransactionStatusPollingOptions()
) async throws -> SendTransactionResponse
```

Expand All @@ -432,7 +434,9 @@ Full-parameter overload:
func sendTransaction(
network: Network,
request: SendTransactionRequest,
selectFeeOption: FeeOptionSelector? = nil
selectFeeOption: FeeOptionSelector? = nil,
waitForStatus: Bool = true,
statusPolling: TransactionStatusPollingOptions = TransactionStatusPollingOptions()
) async throws -> SendTransactionResponse
```

Expand All @@ -445,7 +449,9 @@ func callContract(
method: String,
args: [AbiArg]?,
selectFeeOption: FeeOptionSelector? = nil,
mode: TransactionMode = .relayer
mode: TransactionMode = .relayer,
waitForStatus: Bool = true,
statusPolling: TransactionStatusPollingOptions = TransactionStatusPollingOptions()
) async throws -> SendTransactionResponse
```

Expand Down Expand Up @@ -530,9 +536,11 @@ func getTokenBalances(
Fetches token balances for a wallet on a supported network. Omit `contractAddress` to list balances across contracts. Use `page` to request later pages or a custom page size.

```swift
guard let walletAddress = oms.wallet.walletAddress else { return }

let result = try await oms.indexer.getTokenBalances(
network: .polygon,
walletAddress: oms.wallet.walletAddress,
walletAddress: walletAddress,
includeMetadata: true,
page: TokenBalancesPageRequest(page: 1, pageSize: 100)
)
Expand All @@ -550,9 +558,11 @@ func getNativeTokenBalance(
Fetches the native token balance for a wallet on a supported network. Returns `nil` when the indexer response does not include a balance object.

```swift
guard let walletAddress = oms.wallet.walletAddress else { return }

let balance = try await oms.indexer.getNativeTokenBalance(
network: .polygon,
walletAddress: oms.wallet.walletAddress
walletAddress: walletAddress
)
```

Expand Down Expand Up @@ -760,7 +770,7 @@ fee option when the transaction is sponsored.

| Selector | Description |
|---|---|
| `.firstAvailable` | Uses indexer balances to skip underfunded fee options and picks the first option the wallet can pay. |
| `.firstAvailable` | Uses indexer balances to skip underfunded fee options and picks the first option the wallet can pay. Malformed balance or fee values are treated as not payable. |
| `.custom { options in ... }` | Calls your closure with the full `[FeeOptionWithBalance]` list and expects a `FeeOptionSelection?`. |

```swift
Expand Down Expand Up @@ -902,6 +912,21 @@ The transaction flow returns as soon as status is `.executed` or a non-empty
`txnHash` is available.
`TransactionResult` remains available as a compatibility alias.

### TransactionStatusPollingOptions

```swift
struct TransactionStatusPollingOptions {
let timeoutMs: UInt64?
let intervalMs: UInt64?
let fastIntervalMs: UInt64?
let fastPollCount: Int?
}
```

Controls how `sendTransaction` and `callContract` poll WaaS transaction status
after execute when `waitForStatus` is `true`. Defaults are a 60 second timeout,
400 ms fast polling for the first status checks, then 2 second polling.

### TransactionMode

```swift
Expand Down Expand Up @@ -937,7 +962,7 @@ struct SendTransactionRequest {
}
```

Used with the full `sendTransaction(network:request:selectFeeOption:)` overload.
Used with the full `sendTransaction(network:request:selectFeeOption:waitForStatus:statusPolling:)` overload.
`mode` defaults to `.relayer`.

### TokenBalancesResult
Expand Down
22 changes: 8 additions & 14 deletions Examples/sdk-demo/oms-sdk-demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -294,24 +294,21 @@
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 26.4;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 26.3;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.polygon.oms-sdk-demo";
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
SDKROOT = auto;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
XROS_DEPLOYMENT_TARGET = 26.4;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
Expand Down Expand Up @@ -349,24 +346,21 @@
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 26.4;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 26.3;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.polygon.oms-sdk-demo";
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
SDKROOT = auto;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
XROS_DEPLOYMENT_TARGET = 26.4;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
Expand Down
56 changes: 25 additions & 31 deletions Examples/sdk-demo/oms-sdk-demo/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ final class AppViewModel: ObservableObject {
}

func checkSession() async {
let hasSession = !oms.wallet.walletAddress.isEmpty
let hasSession = oms.wallet.walletAddress != nil
screen = hasSession ? .wallet : .introduction
}

Expand Down Expand Up @@ -573,7 +573,7 @@ private struct IntroductionFeatureRow: View {

VStack(alignment: .leading, spacing: 3) {
DesignText(title, variant: .caption)
.fontWeight(.bold)
.font(.custom(DesignTokens.Typography.family, size: 14).weight(.bold))

DesignText(subtitle, variant: .caption)
}
Expand Down Expand Up @@ -847,7 +847,7 @@ private struct WalletSelectionRow: View {

VStack(alignment: .leading, spacing: 3) {
DesignText(title, variant: .caption)
.fontWeight(.semibold)
.font(.custom(DesignTokens.Typography.family, size: 14).weight(.semibold))
.lineLimit(1)
.truncationMode(.middle)

Expand Down Expand Up @@ -899,7 +899,7 @@ struct WalletWindow: View {
}

private func refreshBalance() async {
guard !vm.oms.wallet.walletAddress.isEmpty else { return }
guard let walletAddress = vm.oms.wallet.walletAddress else { return }
isFetchingBalance = true
clearBalance()
defer { isFetchingBalance = false }
Expand All @@ -908,7 +908,7 @@ struct WalletWindow: View {
let balances = try await vm.oms.indexer.getTokenBalances(
network: selectedNetwork,
contractAddress: usdcContractAddress,
walletAddress: vm.oms.wallet.walletAddress,
walletAddress: walletAddress,
includeMetadata: false
)
if let raw = balances.balances.first?.balance {
Expand All @@ -921,7 +921,7 @@ struct WalletWindow: View {

let nativeTokenBalance = try await vm.oms.indexer.getNativeTokenBalance(
network: selectedNetwork,
walletAddress: vm.oms.wallet.walletAddress
walletAddress: walletAddress
)
if let raw = nativeTokenBalance?.balance {
nativeBalance = formatNativeTokenBalance(raw)
Expand Down Expand Up @@ -970,7 +970,7 @@ struct WalletWindow: View {
}

private var walletTab: some View {
NavigationStack {
NavigationView {
ScrollView {
VStack(spacing: 24) {
walletHeader
Expand All @@ -987,7 +987,7 @@ struct WalletWindow: View {
.task {
await refreshBalance()
}
.onChange(of: selectedNetwork) {
.onChange(of: selectedNetwork) { _ in
Task { await refreshBalance() }
}
}
Expand Down Expand Up @@ -1015,15 +1015,16 @@ struct WalletWindow: View {
private var walletAddressBar: some View {
VStack(spacing: 8) {
HStack(spacing: 6) {
Text(collapsedAddress(vm.oms.wallet.walletAddress))
Text(collapsedAddress(vm.oms.wallet.walletAddress ?? ""))
.font(.system(size: 22, weight: .semibold, design: .monospaced))
.foregroundStyle(DesignTokens.Color.primaryText)
.lineLimit(1)
.truncationMode(.middle)
.textSelection(.enabled)

Button {
Clipboard.copy(vm.oms.wallet.walletAddress)
guard let walletAddress = vm.oms.wallet.walletAddress else { return }
Clipboard.copy(walletAddress)
didCopy = true
Task {
try? await Task.sleep(nanoseconds: 1_500_000_000)
Expand All @@ -1035,7 +1036,7 @@ struct WalletWindow: View {
.foregroundStyle(didCopy ? DesignTokens.Color.success : DesignTokens.Color.info)
}
.buttonStyle(.plain)
.disabled(vm.oms.wallet.walletAddress.isEmpty)
.disabled(vm.oms.wallet.walletAddress == nil)
.help(didCopy ? "Copied" : "Copy address")
}

Expand Down Expand Up @@ -1341,8 +1342,8 @@ struct SendTransactionWindow: View {
.environmentObject(vm)
}
.onAppear {
if toText.isEmpty {
toText = vm.oms.wallet.walletAddress
if toText.isEmpty, let walletAddress = vm.oms.wallet.walletAddress {
toText = walletAddress
}
}
}
Expand Down Expand Up @@ -1457,20 +1458,12 @@ struct CallContractWindow: View {
}

ForEach($args) { $arg in
ViewThatFits(in: .horizontal) {
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 8) {
abiTypeField(arg: $arg)
abiValueField(arg: $arg)
removeAbiArgButton(arg: arg)
}

VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 8) {
abiTypeField(arg: $arg)
removeAbiArgButton(arg: arg)
}
abiValueField(arg: $arg)
}
abiValueField(arg: $arg)
}
}
}
Expand Down Expand Up @@ -1830,7 +1823,7 @@ private struct NavigationScreenContainer<Content: View>: View {
}

var body: some View {
NavigationStack {
NavigationView {
VStack(spacing: 0) {
content
}
Expand Down Expand Up @@ -1873,7 +1866,7 @@ private struct ModalContainer<Content: View>: View {
}

var body: some View {
NavigationStack {
NavigationView {
ScrollView {
VStack(alignment: .leading, spacing: 20) {
HStack(alignment: .center, spacing: 12) {
Expand Down Expand Up @@ -1935,7 +1928,9 @@ private struct FieldGroup<Content: View>: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
DesignText(title, variant: titleStyle == .secondary ? .caption : .body)
.fontWeight(.semibold)
.font(titleStyle == .secondary
? Font.custom(DesignTokens.Typography.family, size: 14).weight(.semibold)
: Font.custom(DesignTokens.Typography.family, size: 16).weight(.semibold))

content
}
Expand Down Expand Up @@ -2053,7 +2048,7 @@ private struct ResultPanel: View {
var body: some View {
Panel {
DesignText(title, variant: .body)
.fontWeight(.semibold)
.font(.custom(DesignTokens.Typography.family, size: 16).weight(.semibold))

CopyableResult(text: text)
}
Expand All @@ -2066,7 +2061,7 @@ private struct TransactionResultPanel: View {
var body: some View {
Panel {
DesignText("Transaction result", variant: .body)
.fontWeight(.semibold)
.font(.custom(DesignTokens.Typography.family, size: 16).weight(.semibold))

ResultRow(label: "Status", value: result.status.wireValue)
ResultRow(label: "Transaction ID", value: result.txnId)
Expand All @@ -2085,7 +2080,7 @@ private struct ResultRow: View {
var body: some View {
VStack(alignment: .leading, spacing: 6) {
DesignText(label, variant: .caption)
.fontWeight(.semibold)
.font(.custom(DesignTokens.Typography.family, size: 14).weight(.semibold))

CopyableResult(text: value)
}
Expand All @@ -2100,8 +2095,7 @@ struct CopyableResult: View {
var body: some View {
HStack(spacing: 8) {
Text(text)
.font(.footnote)
.monospaced()
.font(.system(.footnote, design: .monospaced))
.foregroundStyle(DesignTokens.Color.secondaryText)
.lineLimit(1)
.truncationMode(.middle)
Expand Down
Loading
Loading