Skip to content

Instantly share code, notes, and snippets.

@valldrac
Created June 3, 2023 00:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save valldrac/54ff6842e4cc6d624ab893f4e839b2ae to your computer and use it in GitHub Desktop.
Save valldrac/54ff6842e4cc6d624ab893f4e839b2ae to your computer and use it in GitHub Desktop.
suspend fun restoreAndRefreshExample(context: Context) = coroutineScope {
// Connect to the SDK wallet service.
val provider = WalletProvider.connect(context)
// Define 2 onion nodes.
val torNodes = listOf(
"http://3g2upl4pq6kufc4m.onion:18082",
"http://33y6fjyhs3phzfjj.onion:18082",
).map { url -> RemoteNode(Uri.parse(url)) }
// Create a SOCKS proxy to connect to Tor and build an instance
// of OkHttpClient using the proxy.
val proxy = Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved("localhost", 9050))
val okHttpClient = OkHttpClient().newBuilder().proxy(proxy).build()
// Restore a MAINNET wallet by providing the secret key and creation date.
// For an offline wallet, set client parameter to null.
val wallet = provider.restoreWallet(
network = MoneroNetwork.Mainnet,
client = RpcClient.forNetwork(
MoneroNetwork.Mainnet,
remoteNodes = flowOf(torNodes), // API expects a flow of nodes. Using a static list here for simplicity.
loadBalancerRule = RoundRobinRule(),
httpClient = okHttpClient
),
secretSpendKey = SecretKey("d2ca26e22489bd9871c910c58dee3ab08e66b9d566825a064c8c0af061cd8706".parseHex()),
accountCreationTime = Instant.parse("2017-12-03T10:15:30.00Z")
)
// Print the primary address of the wallet.
println("New wallet address is ${wallet.primaryAddress}")
// Implement the simple storage for the wallet using an AtomicFile named "unencrypted.wallet".
// A real app should add its wallet encryption layer here.
wallet.dataStore = object : WalletDataStore {
private val file: AtomicFile = AtomicFile(File("unencrypted.wallet"))
override suspend fun write(writer: (FileOutputStream) -> Unit) =
file.startWrite().use { output ->
writer(output)
file.finishWrite(output)
}
override suspend fun read(): FileInputStream = file.openRead()
}
// Auto-save the wallet every 1 minute.
launch {
while (isActive) {
wallet.commit()
delay(60.seconds)
}
}
// Start listening to balance updates.
launch {
// The Ledger is an immutable object that contains a balance query object
// and the list of owned transactions detected so far.
wallet.ledger().collect { ledger ->
// When an update is received, print the height and total balance.
val amountFormatted = MoneroCurrency.format(ledger.balance.totalAmount)
val height = ledger.checkedAtBlockHeight
println("Balance @ block height $height: XMR $amountFormatted")
}
}
// Continuously refresh the wallet by calling awaitRefresh() until it receives an error.
// Refreshing does not block the wallet. Other functions like commit() can be called simultaneously.
val syncJob = launch {
while (isActive) {
val result = wallet.awaitRefresh()
if (result.isError()) {
cancel("Error syncing the wallet")
}
// Prints the block height and waits 15 seconds before refreshing again.
println("Refresh done. Height: ${result.blockHeight}")
delay(15.seconds)
}
}
// Wait until scope is canceled.
syncJob.join()
// Close the wallet
wallet.close()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment