[SDK] Fix rest client and wasm (#341)

* Fixes

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>

* Fixes to rest client

* Fixes to wasm

---------

Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>
This commit is contained in:
Pietralberto Mazza
2024-10-01 19:00:25 +02:00
committed by GitHub
parent a3deb2d596
commit 26bcbc8163
7 changed files with 115 additions and 69 deletions

View File

@@ -38,6 +38,7 @@ func NewClient(aspUrl string) (client.ASPClient, error) {
if err != nil {
return nil, err
}
// TODO: use twice the round interval.
reqTimeout := 15 * time.Second
treeCache := utils.NewCache[tree.CongestionTree]()
@@ -223,25 +224,19 @@ func (a *restClient) SubmitSignedForfeitTxs(
func (a *restClient) GetEventStream(
ctx context.Context, paymentID string,
) (<-chan client.RoundEventChannel, func(), error) {
ctx, cancel := context.WithTimeout(ctx, a.requestTimeout)
eventsCh := make(chan client.RoundEventChannel)
stopCh := make(chan struct{})
go func(payID string) {
go func(payID string, eventsCh chan client.RoundEventChannel) {
ticker := time.NewTicker(1 * time.Second)
defer close(eventsCh)
defer close(stopCh)
timeout := time.After(a.requestTimeout)
defer ticker.Stop()
for {
select {
case <-stopCh:
case <-ctx.Done():
return
case <-timeout:
eventsCh <- client.RoundEventChannel{
Err: fmt.Errorf("timeout reached"),
}
return
default:
case <-ticker.C:
event, err := a.Ping(ctx, payID)
if err != nil {
eventsCh <- client.RoundEventChannel{
@@ -255,17 +250,11 @@ func (a *restClient) GetEventStream(
Event: event,
}
}
time.Sleep(1 * time.Second)
}
}
}(paymentID)
}(paymentID, eventsCh)
close := func() {
stopCh <- struct{}{}
}
return eventsCh, close, nil
return eventsCh, cancel, nil
}
func (a *restClient) Ping(

View File

@@ -2,20 +2,23 @@
This example demonstrates how to compile ARK Go SDK to WebAssembly and use it in a web page.
1. Create a Go file with the main package, check [main.go](main.go).
2. Copy `wasm_exec.js`:
1. Copy `wasm_exec.js` to a new directory:
```bash
cp $(go env GOROOT)/misc/wasm/wasm_exec.js .
```
3. Build the Go code to WebAssembly:
2. On the root directory of this repo, build the Go code to WebAssembly:
```bash
GOOS=js GOARCH=wasm go build -o main.wasm main.go
make build-wasm
```
3. Move the wasm file to your directory
```bash
mv <repo>/pkg/client-sdk/build/ark-sdk.wasm .
4. Load the WebAssembly module in a web page, check [index.html](index.html).
5. Serve the files:

View File

@@ -44,8 +44,7 @@
try {
const addresses = await receive();
logMessage("Offchain address: " + addresses.offchainAddr);
logMessage("Onchain address: " + addresses.onchainAddr);
logMessage("If in regtest faucet onchain address: " + addresses.onchainAddr);
logMessage("Boarding address: " + addresses.boardingAddr);
} catch (err) {
logMessage("Receive error: " + err.message);
}
@@ -53,8 +52,10 @@
async function getBalance() {
const bal = await balance(false);
logMessage("Onchain balance: " + bal.onchain_balance)
logMessage("Offchain balance: " + bal.offchain_balance)
logMessage("Offchain balance: " + bal.offchainBalance)
logMessage("Onchain balance: ")
logMessage(" Spendable: " + bal.onchainBalance.spendable)
logMessage(" Locked: " + bal.onchainBalance.locked)
}
@@ -88,6 +89,33 @@
}
}
async function claimVtxos() {
const password = document.getElementById("c_password").value;
if (!password) {
logMessage("Claim error: password is required");
return;
}
try {
await unlock(password);
const txID = await claim();
logMessage("Claimed money with tx ID: " + txID);
} catch (err) {
logMessage("Claim error: " + err.message);
} finally {
await lock(password);
}
}
async function history() {
try {
const history = await getTransactionHistory();
logMessage("Tx history: " + history);
} catch (err) {
logMessage("Tx history error: " + err.message);
}
}
async function config() {
try {
const aspUrl = await getAspUrl();
@@ -112,30 +140,6 @@
logMessage("Config error: " + err.message);
}
}
async function board() {
const amountStr = document.getElementById("amount").value;
const amount = parseInt(amountStr, 10);
const password = document.getElementById("o_password").value;
if (!password) {
logMessage("Onboard error: password is required");
return;
}
try {
console.log("unlocking...");
await unlock(password);
console.log(amount, password);
console.log("onboarding...");
const txID = await onboard(amount);
logMessage("Onboarded with amount: " + amount + " and txID: " + txID + ", if in regtest mine a block");
} catch (err) {
logMessage("Onboard error: " + err.message);
} finally {
await lock(password);
}
}
</script>
</head>
<body>
@@ -154,17 +158,19 @@
<div>
<button onclick="getBalance()">Balance</button>
</div>
<div>
<button onclick="board()">Onboard</button>
<input type="text" id="amount" placeholder="Amount">
<input type="password" id="o_password" placeholder="password">
</div>
<div>
<button onclick="send()">Send</button>
<input type="text" id="sendAddress" placeholder="Offchain Address">
<input type="text" id="amountToSend" placeholder="Amount">
<input type="password" id="s_password" placeholder="password">
</div>
<div>
<button onclick="claimVtxos()">Claim</button>
<input type="password" id="c_password" placeholder="password">
</div>
<div>
<button onclick="history()">History</button>
</div>
<div>
<button onclick="config()">Config</button>
</div>

View File

@@ -30,8 +30,10 @@ func init() {
js.Global().Set("receive", ReceiveWrapper())
js.Global().Set("sendOnChain", SendOnChainWrapper())
js.Global().Set("sendOffChain", SendOffChainWrapper())
js.Global().Set("claim", ClaimWrapper())
js.Global().Set("unilateralRedeem", UnilateralRedeemWrapper())
js.Global().Set("collaborativeRedeem", CollaborativeRedeemWrapper())
js.Global().Set("getTransactionHistory", GetTransactionHistoryWrapper())
js.Global().Set("log", LogWrapper())
js.Global().Set("getAspUrl", GetAspUrlWrapper())

View File

@@ -6,9 +6,12 @@ package browser
import (
"context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"strconv"
"syscall/js"
"time"
arksdk "github.com/ark-network/ark/pkg/client-sdk"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
@@ -119,21 +122,25 @@ func BalanceWrapper() js.Func {
}
var (
onchainBalance int
onchainSpendableBalance int
onchainLockedBalance int
offchainBalance int
)
if resp == nil {
onchainBalance = 0
offchainBalance = 0
} else {
onchainBalance = int(resp.OnchainBalance.SpendableAmount)
if resp != nil {
onchainSpendableBalance = int(resp.OnchainBalance.SpendableAmount)
for _, b := range resp.OnchainBalance.LockedAmount {
onchainLockedBalance += int(b.Amount)
}
offchainBalance = int(resp.OffchainBalance.Total)
}
result := map[string]interface{}{
"onchain_balance": onchainBalance,
"offchain_balance": offchainBalance,
"onchainBalance": map[string]interface{}{
"spendable": onchainSpendableBalance,
"locked": onchainLockedBalance,
},
"offchainBalance": offchainBalance,
}
return js.ValueOf(result), nil
@@ -204,6 +211,21 @@ func SendOffChainWrapper() js.Func {
})
}
func ClaimWrapper() js.Func {
return JSPromise(func(args []js.Value) (interface{}, error) {
if len(args) != 0 {
return nil, errors.New("invalid number of args")
}
resp, err := arkSdkClient.Claim(context.Background())
if err != nil {
return nil, err
}
return js.ValueOf(resp), nil
})
}
func UnilateralRedeemWrapper() js.Func {
return JSPromise(func(args []js.Value) (interface{}, error) {
return nil, arkSdkClient.UnilateralRedeem(context.Background())
@@ -229,6 +251,32 @@ func CollaborativeRedeemWrapper() js.Func {
})
}
func GetTransactionHistoryWrapper() js.Func {
return JSPromise(func(args []js.Value) (interface{}, error) {
history, err := arkSdkClient.GetTransactionHistory(context.Background())
if err != nil {
return nil, err
}
rawHistory := make([]map[string]interface{}, 0)
for _, record := range history {
rawHistory = append(rawHistory, map[string]interface{}{
"boardingTxid": record.BoardingTxid,
"roundTxid": record.RoundTxid,
"redeemTxid": record.RedeemTxid,
"amount": strconv.Itoa(int(record.Amount)),
"type": record.Type,
"isPending": record.IsPending,
"createdAt": record.CreatedAt.Format(time.RFC3339),
})
}
result, err := json.MarshalIndent(rawHistory, "", " ")
if err != nil {
return nil, err
}
return js.ValueOf(string(result)), nil
})
}
func GetAspUrlWrapper() js.Func {
return js.FuncOf(func(this js.Value, p []js.Value) interface{} {
data, _ := arkSdkClient.GetConfigData(context.Background())

View File

@@ -421,7 +421,6 @@ func (s *covenantService) startRound() {
round := domain.NewRound(dustAmount)
//nolint:all
round.StartRegistration()
s.lastEvent = nil
s.currentRound = round
defer func() {

View File

@@ -712,7 +712,6 @@ func (s *covenantlessService) startRound() {
round := domain.NewRound(dustAmount)
//nolint:all
round.StartRegistration()
s.lastEvent = nil
s.currentRound = round
defer func() {