From 3473a4413b4dd1328e2bfdc5145ba8e44ceb9365 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 5 Mar 2025 16:40:55 +0300 Subject: [PATCH 01/50] add pool deposit,swap and quote endpoints --- config/config.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index 6ebb5bc..c9f323e 100644 --- a/config/config.go +++ b/config/config.go @@ -15,7 +15,10 @@ const ( voucherHoldingsPathPrefix = "/api/v1/holdings" voucherTransfersPathPrefix = "/api/v1/transfers/last10" voucherDataPathPrefix = "/api/v1/token" - AliasPrefix = "api/v1/alias" + aliasPrefix = "api/v1/alias" + poolDepositPrefix = "/api/v2/pool/deposit" + poolSwapQoutePrefix = "/api/v2/pool/quote" + poolSwapPrefix = "/api/v2/pool/swap" ) var ( @@ -34,6 +37,9 @@ var ( VoucherTransfersURL string VoucherDataURL string CheckAliasURL string + PoolDepositURL string + PoolSwapQuoteURL string + PoolSwapURL string ) func setBase() error { @@ -68,6 +74,10 @@ func LoadConfig() error { VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) VoucherDataURL, _ = url.JoinPath(dataURLBase, voucherDataPathPrefix) - CheckAliasURL, _ = url.JoinPath(dataURLBase, AliasPrefix) + CheckAliasURL, _ = url.JoinPath(dataURLBase, aliasPrefix) + PoolDepositURL, _ = url.JoinPath(custodialURLBase, poolDepositPrefix) + PoolSwapQuoteURL, _ = url.JoinPath(custodialURLBase, poolSwapQoutePrefix) + PoolSwapURL, _ = url.JoinPath(custodialURLBase, poolSwapPrefix) + return nil } From a1fe416f51da814a5644706d266319373304985d Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 5 Mar 2025 16:41:54 +0300 Subject: [PATCH 02/50] implement pool deposit,swap and quote endpoints --- remote/http/service.go | 80 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/remote/http/service.go b/remote/http/service.go index aca8ae0..86a856a 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -239,6 +239,86 @@ func resolveAliasAddress(ctx context.Context, alias string) (*models.AliasAddres return &r, err } +func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { + var r models.PoolDepositResult + + //pool deposit payload + payload := map[string]string{ + "amount": amount, + "from": from, + "poolAddress": poolAddress, + "tokenAddress": tokenAddress, + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, err + } + req, err := http.NewRequest("POST", config.TokenTransferURL, bytes.NewBuffer(payloadBytes)) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + if err != nil { + return nil, err + } + return &r, nil +} + +func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { + var r models.PoolSwapQuoteResult + + //pool swap quote payload + payload := map[string]string{ + "amount": amount, + "from": from, + "fromTokenAddress": fromTokenAddress, + "poolAddress": poolAddress, + "toTokenAddress": toTokenAddress, + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, err + } + req, err := http.NewRequest("POST", config.PoolSwapQuoteURL, bytes.NewBuffer(payloadBytes)) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + if err != nil { + return nil, err + } + return &r, nil +} + +func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { + var r models.PoolSwapResult + + //swap payload + payload := map[string]string{ + "amount": amount, + "from": from, + "fromTokenAddress": fromTokenAddress, + "poolAddress": poolAddress, + "toTokenAddress": toTokenAddress, + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, err + } + req, err := http.NewRequest("POST", config.PoolSwapQuoteURL, bytes.NewBuffer(payloadBytes)) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + if err != nil { + return nil, err + } + return &r, nil +} + // TODO: Use actual custodial api to request available alias func (as *HTTPAccountService) RequestAlias(ctx context.Context, publicKey string, hint string) (*models.RequestAliasResult, error) { if as.SS == nil { From aef8efa2bf26700f4c14bb48f14bf5f26f72e73e Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 5 Mar 2025 16:42:55 +0300 Subject: [PATCH 03/50] add pool api responses --- models/pool_swap_response.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 models/pool_swap_response.go diff --git a/models/pool_swap_response.go b/models/pool_swap_response.go new file mode 100644 index 0000000..8842d67 --- /dev/null +++ b/models/pool_swap_response.go @@ -0,0 +1,14 @@ +package models + +type PoolDepositResult struct { + TrackingId string `json:"trackingId"` +} + +type PoolSwapQuoteResult struct { + IncludesFeesDeduction bool `json:"includesFeesDeduction"` + OutValue string `json:"outValue"` +} + +type PoolSwapResult struct { + TrackingId string `json:"trackingId"` +} From 35f24b5183758e34032fb77be8358f2627233fcc Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 6 Mar 2025 18:14:34 +0300 Subject: [PATCH 04/50] Use the latest ussd-data-service --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0d62c17..4b25b5f 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta - github.com/grassrootseconomics/ussd-data-service v1.2.0-beta + github.com/grassrootseconomics/ussd-data-service v1.4.0-beta github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index c88d977..6653efe 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ github.com/grassrootseconomics/eth-custodial v1.3.0-beta h1:twrMBhl89GqDUL9PlkzQ github.com/grassrootseconomics/eth-custodial v1.3.0-beta/go.mod h1:7uhRcdnJplX4t6GKCEFkbeDhhjlcaGJeJqevbcvGLZo= github.com/grassrootseconomics/ussd-data-service v1.2.0-beta h1:fn1gwbWIwHVEBtUC2zi5OqTlfI/5gU1SMk0fgGixIXk= github.com/grassrootseconomics/ussd-data-service v1.2.0-beta/go.mod h1:omfI0QtUwIdpu9gMcUqLMCG8O1XWjqJGBx1qUMiGWC0= +github.com/grassrootseconomics/ussd-data-service v1.4.0-beta h1:4fMd/3h2ZIhRg4GdHQmRw5FfD3MpJvFNNJQo+Q27f5M= +github.com/grassrootseconomics/ussd-data-service v1.4.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= From f723e0aa45cc49d4fb39878897793584d33d9948 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 7 Mar 2025 08:09:41 +0300 Subject: [PATCH 05/50] add sample test data --- dev/data/swap_from.json | 32 ++++++++++++++++++++++++++++++ dev/data/swap_to.json | 14 ++++++++++++++ dev/data/top_pools.json | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 dev/data/swap_from.json create mode 100644 dev/data/swap_to.json create mode 100644 dev/data/top_pools.json diff --git a/dev/data/swap_from.json b/dev/data/swap_from.json new file mode 100644 index 0000000..e523972 --- /dev/null +++ b/dev/data/swap_from.json @@ -0,0 +1,32 @@ +{ + "ok": true, + "description": "Swap from list", + "result": { + "filtered": [ + { + "contractAddress": "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + "tokenSymbol": "AMANI", + "tokenDecimals": "6", + "balance": "" + }, + { + "contractAddress": "0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674", + "tokenSymbol": "AMUA", + "tokenDecimals": "6", + "balance": "" + }, + { + "contractAddress": "0x371455a30fc62736145Bd8429Fcc6481186f235F", + "tokenSymbol": "BAHARI", + "tokenDecimals": "6", + "balance": "" + }, + { + "contractAddress": "0x7cA6113b59c24a880F382C7E12d609a6Eb05246b", + "tokenSymbol": "BANGLA", + "tokenDecimals": "6", + "balance": "" + } + ] + } +} \ No newline at end of file diff --git a/dev/data/swap_to.json b/dev/data/swap_to.json new file mode 100644 index 0000000..c8906b6 --- /dev/null +++ b/dev/data/swap_to.json @@ -0,0 +1,14 @@ +{ + "ok": true, + "description": "Swap to list", + "result": { + "filtered": [ + { + "contractAddress": "0x765DE816845861e75A25fCA122bb6898B8B1282a", + "tokenSymbol": "cUSD", + "tokenDecimals": "18", + "balance": "" + } + ] + } +} \ No newline at end of file diff --git a/dev/data/top_pools.json b/dev/data/top_pools.json new file mode 100644 index 0000000..85e120c --- /dev/null +++ b/dev/data/top_pools.json @@ -0,0 +1,43 @@ +{ + "ok": true, + "description": "Top 5 pools sorted by swaps", + "result": { + "topPools": [ + { + "poolName": "Kenya ROLA Pool", + "poolSymbol": "ROLA", + "poolContractAddress": "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + "limiterAddress": "", + "voucherRegistry": "" + }, + { + "poolName": "Nairobi ROLA Pool", + "poolSymbol": "NAIROBI", + "poolContractAddress": "0xB0660Ac1Ee3d32ea35bc728D7CA1705Fa5A37528", + "limiterAddress": "", + "voucherRegistry": "" + }, + { + "poolName": "Friends of Kiriba Ecosystem ", + "poolSymbol": "FRIENDS", + "poolContractAddress": "0xC4848263821FA02baB2181910A2eFb9CECb2c21C", + "limiterAddress": "", + "voucherRegistry": "" + }, + { + "poolName": "Resilient Community Waqfs", + "poolSymbol": "REZILIENS", + "poolContractAddress": "0x1e40951d7a28147D8B4A554C60c42766C92e2Fc6", + "limiterAddress": "", + "voucherRegistry": "" + }, + { + "poolName": "GrE Tech", + "poolSymbol": "GRET", + "poolContractAddress": "0xb7B9d0A264eD1a8E2418571B7AC5933C79C9c2B8", + "limiterAddress": "", + "voucherRegistry": "" + } + ] + } +} \ No newline at end of file From b05734f976cc8dc4d06fb8d189c3917f46e51e91 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 7 Mar 2025 08:11:04 +0300 Subject: [PATCH 06/50] feat: add fetch pools,swappable pool vouchers --- dev/api.go | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/dev/api.go b/dev/api.go index fc68c29..1ebbe7c 100644 --- a/dev/api.go +++ b/dev/api.go @@ -6,7 +6,9 @@ import ( "crypto/sha1" "encoding/json" "fmt" + "log" "math/rand" + "os" "regexp" "strconv" "strings" @@ -91,6 +93,11 @@ type Voucher struct { Location string `json: "location"` } +type Pool struct { + vouchers []Voucher + poolLimit map[string]string +} + type DevAccountService struct { db db.Db accounts map[string]Account @@ -106,6 +113,7 @@ type DevAccountService struct { defaultAccount string emitterFunc event.EmitterFunc pfx []byte + pool Pool } func NewDevAccountService(ctx context.Context, ss storage.StorageService) *DevAccountService { @@ -118,6 +126,7 @@ func NewDevAccountService(ctx context.Context, ss storage.StorageService) *DevAc txs: make(map[string]Tx), txsTrack: make(map[string]string), autoVoucherValue: make(map[string]int), + pool: Pool{}, defaultAccount: zeroAddress, pfx: []byte("__"), } @@ -171,6 +180,15 @@ func (das *DevAccountService) loadAccount(ctx context.Context, pubKey string, v return nil } +func (p *Pool) hasVoucher(voucherAddress string) bool { + for _, value := range p.vouchers { + if value.Address == voucherAddress { + return true + } + } + return false +} + func (das *DevAccountService) loadTx(ctx context.Context, hsh string, v []byte) error { var mytx Tx @@ -415,6 +433,74 @@ func (das *DevAccountService) CreateAccount(ctx context.Context) (*models.Accoun }, nil } +func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { + sym, ok := das.vouchersAddress[tokenAddress] + if !ok { + return nil, fmt.Errorf("voucher address %v not found", tokenAddress) + } + uid, err := uuid.NewV4() + if err != nil { + return nil, err + } + + voucher, ok := das.vouchers[sym] + if !ok { + return nil, fmt.Errorf("voucher address %v found but does not resolve", tokenAddress) + } + + das.pool = Pool{ + vouchers: append(das.pool.vouchers, voucher), + poolLimit: map[string]string{tokenAddress: amount}, + } + return &models.PoolDepositResult{ + TrackingId: uid.String(), + }, nil +} + +func (das *DevAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { + _, ok := das.accounts[from] + if !ok { + return nil, fmt.Errorf("account not found (publickey): %v", from) + } + //resolve the token address you are trying to swap from(fromTokenAddress) + _, ok = das.vouchersAddress[fromTokenAddress] + if !ok { + return nil, fmt.Errorf("voucher address %v not found", fromTokenAddress) + } + p := das.pool + + //check if pool has voucher to swap to + if !p.hasVoucher(toTokenAddress) { + return nil, fmt.Errorf("Voucher with address: %v not found in the pool", toTokenAddress) + } + //Return a a quote that is equal to the amount enter + return &models.PoolSwapQuoteResult{IncludesFeesDeduction: false, OutValue: amount}, nil +} + +func (das *DevAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { + uid, err := uuid.NewV4() + if err != nil { + return nil, err + } + + _, ok := das.accounts[from] + if !ok { + return nil, fmt.Errorf("account not found (publickey): %v", from) + } + _, ok = das.vouchersAddress[fromTokenAddress] + if !ok { + return nil, fmt.Errorf("voucher address %v not found", fromTokenAddress) + } + p := das.pool + + //check if pool has voucher to swap to + if !p.hasVoucher(toTokenAddress) { + return nil, fmt.Errorf("Voucher with address: %v not found in the pool", toTokenAddress) + } + + return &models.PoolSwapResult{TrackingId: uid.String()}, nil +} + func (das *DevAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) { var ok bool _, ok = das.accounts[publicKey] @@ -653,3 +739,72 @@ func (das *DevAccountService) RequestAlias(ctx context.Context, publicKey string Alias: alias, }, nil } + +func (das *DevAccountService) FetchTopPools(ctx context.Context) ([]models.Pool, error) { + var ( + r struct { + OK bool `json:"ok"` + Description string `json:"description"` + Result struct { + Pools []models.Pool `json:"topPools"` + } `json:"result"` + } + ) + data, err := os.ReadFile("./data/top_pools.json") + if err != nil { + log.Fatal(err) + } + + err = json.Unmarshal(data, &r) + if err != nil { + log.Fatal(err) + } + + return r.Result.Pools, nil +} + +func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { + var ( + r struct { + OK bool `json:"ok"` + Description string `json:"description"` + Result struct { + SwappableVouchers []models.SwappableVoucher `json:"filtered"` + } `json:"result"` + } + ) + data, err := os.ReadFile("./data/swap_from.json") + if err != nil { + log.Fatal(err) + } + + err = json.Unmarshal(data, &r) + if err != nil { + log.Fatal(err) + } + + return r.Result.SwappableVouchers, nil +} + +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { + var ( + r struct { + OK bool `json:"ok"` + Description string `json:"description"` + Result struct { + SwappableVouchers []models.SwappableVoucher `json:"filtered"` + } `json:"result"` + } + ) + data, err := os.ReadFile("./data/swap_to.json") + if err != nil { + log.Fatal(err) + } + + err = json.Unmarshal(data, &r) + if err != nil { + log.Fatal(err) + } + + return r.Result.SwappableVouchers, nil +} From 67d7ec156728ead0166d0f83b616aa98e2d8d592 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 7 Mar 2025 08:11:33 +0300 Subject: [PATCH 07/50] add pool structs --- models/pool.go | 10 ++++++++++ models/voucher_data_result.go | 7 +++++++ 2 files changed, 17 insertions(+) create mode 100644 models/pool.go diff --git a/models/pool.go b/models/pool.go new file mode 100644 index 0000000..9e784b3 --- /dev/null +++ b/models/pool.go @@ -0,0 +1,10 @@ +package models + + +type Pool struct { + PoolName string `json:"poolName"` + PoolSymbol string `json:"poolSymbol"` + PoolContractAddress string `json:"poolContractAddress"` + LimiterAddress string `json:"limiterAddress"` + VoucherRegistry string `json:"voucherRegistry"` +} diff --git a/models/voucher_data_result.go b/models/voucher_data_result.go index 9a10831..1311482 100644 --- a/models/voucher_data_result.go +++ b/models/voucher_data_result.go @@ -8,3 +8,10 @@ type VoucherDataResult struct { TokenCommodity string `json:"tokenCommodity"` TokenLocation string `json:"tokenLocation"` } + +type SwappableVoucher struct { + ContractAddress string `json:"contractAddress"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + Balance string `json:"balance"` +} From e8c58a8f3308ea724ad14eb4618d700c63d6cc52 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 7 Mar 2025 08:13:15 +0300 Subject: [PATCH 08/50] feat: implement fetch pools,pool swappable vouchers with dummy data --- remote/http/service.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/remote/http/service.go b/remote/http/service.go index 86a856a..7bad334 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -239,6 +239,11 @@ func resolveAliasAddress(ctx context.Context, alias string) (*models.AliasAddres return &r, err } +func (as *HTTPAccountService) FetchTopPools(ctx context.Context) ([]models.Pool, error) { + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.FetchTopPools(ctx) +} + func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { var r models.PoolDepositResult @@ -292,6 +297,14 @@ func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from return &r, nil } +func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { + return as.GetPoolSwappableFromVouchers(ctx) +} + +func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { + return as.GetPoolSwappableVouchers(ctx) +} + func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { var r models.PoolSwapResult From d7ae1cc096533eee9f7e7204d53da87319a9007a Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 13:59:05 +0300 Subject: [PATCH 09/50] Include the account's public key --- remote/http/service.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index 7bad334..3792f5b 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -239,9 +239,9 @@ func resolveAliasAddress(ctx context.Context, alias string) (*models.AliasAddres return &r, err } -func (as *HTTPAccountService) FetchTopPools(ctx context.Context) ([]models.Pool, error) { +func (as *HTTPAccountService) FetchTopPools(ctx context.Context, publicKey string) ([]dataserviceapi.PoolDetails, error) { svc := dev.NewDevAccountService(ctx, as.SS) - return svc.FetchTopPools(ctx) + return svc.FetchTopPools(ctx, publicKey) } func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { @@ -297,12 +297,12 @@ func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from return &r, nil } -func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { - return as.GetPoolSwappableFromVouchers(ctx) +func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + return as.GetPoolSwappableFromVouchers(ctx, publicKey) } -func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { - return as.GetPoolSwappableVouchers(ctx) +func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + return as.GetPoolSwappableVouchers(ctx, publicKey) } func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { From 52e1be1104e5170e8eef2728a699c7a984f8bc48 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 14:00:16 +0300 Subject: [PATCH 10/50] Return an array of data instead of reading from the file --- dev/api.go | 133 +++++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 59 deletions(-) diff --git a/dev/api.go b/dev/api.go index 1ebbe7c..5e9ca9b 100644 --- a/dev/api.go +++ b/dev/api.go @@ -6,9 +6,7 @@ import ( "crypto/sha1" "encoding/json" "fmt" - "log" "math/rand" - "os" "regexp" "strconv" "strings" @@ -740,71 +738,88 @@ func (das *DevAccountService) RequestAlias(ctx context.Context, publicKey string }, nil } -func (das *DevAccountService) FetchTopPools(ctx context.Context) ([]models.Pool, error) { - var ( - r struct { - OK bool `json:"ok"` - Description string `json:"description"` - Result struct { - Pools []models.Pool `json:"topPools"` - } `json:"result"` - } - ) - data, err := os.ReadFile("./data/top_pools.json") - if err != nil { - log.Fatal(err) +func (das *DevAccountService) FetchTopPools(ctx context.Context, publicKey string) ([]dataserviceapi.PoolDetails, error) { + topPools := []dataserviceapi.PoolDetails{ + { + PoolName: "Kenya ROLA Pool", + PoolSymbol: "ROLA", + PoolContractAdrress: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "Nairobi ROLA Pool", + PoolSymbol: "NAIROBI", + PoolContractAdrress: "0xB0660Ac1Ee3d32ea35bc728D7CA1705Fa5A37528", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "Friends of Kiriba Ecosystem", + PoolSymbol: "FRIENDS", + PoolContractAdrress: "0xC4848263821FA02baB2181910A2eFb9CECb2c21C", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "Resilient Community Waqfs", + PoolSymbol: "REZILIENS", + PoolContractAdrress: "0x1e40951d7a28147D8B4A554C60c42766C92e2Fc6", + LimiterAddress: "", + VoucherRegistry: "", + }, + { + PoolName: "GrE Tech", + PoolSymbol: "GRET", + PoolContractAdrress: "0xb7B9d0A264eD1a8E2418571B7AC5933C79C9c2B8", + LimiterAddress: "", + VoucherRegistry: "", + }, } - err = json.Unmarshal(data, &r) - if err != nil { - log.Fatal(err) - } - - return r.Result.Pools, nil + return topPools, nil } -func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { - var ( - r struct { - OK bool `json:"ok"` - Description string `json:"description"` - Result struct { - SwappableVouchers []models.SwappableVoucher `json:"filtered"` - } `json:"result"` - } - ) - data, err := os.ReadFile("./data/swap_from.json") - if err != nil { - log.Fatal(err) +func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + swapFromList := []dataserviceapi.TokenHoldings{ + { + ContractAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", + TokenSymbol: "AMANI", + TokenDecimals: "6", + Balance: "", + }, + { + ContractAddress: "0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674", + TokenSymbol: "AMUA", + TokenDecimals: "6", + Balance: "", + }, + { + ContractAddress: "0x371455a30fc62736145Bd8429Fcc6481186f235F", + TokenSymbol: "BAHARI", + TokenDecimals: "6", + Balance: "", + }, + { + ContractAddress: "0x7cA6113b59c24a880F382C7E12d609a6Eb05246b", + TokenSymbol: "BANGLA", + TokenDecimals: "6", + Balance: "", + }, } - err = json.Unmarshal(data, &r) - if err != nil { - log.Fatal(err) - } - - return r.Result.SwappableVouchers, nil + return swapFromList, nil } -func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context) ([]models.SwappableVoucher, error) { - var ( - r struct { - OK bool `json:"ok"` - Description string `json:"description"` - Result struct { - SwappableVouchers []models.SwappableVoucher `json:"filtered"` - } `json:"result"` - } - ) - data, err := os.ReadFile("./data/swap_to.json") - if err != nil { - log.Fatal(err) +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + swapToList := []dataserviceapi.TokenHoldings{ + { + ContractAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", + TokenSymbol: "cUSD", + TokenDecimals: "18", + Balance: "", + }, } - err = json.Unmarshal(data, &r) - if err != nil { - log.Fatal(err) - } - - return r.Result.SwappableVouchers, nil + return swapToList, nil } From a04f7ee66c3557a94d97aa902edf1732563fc4ff Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 14:03:30 +0300 Subject: [PATCH 11/50] Remove unused model structs --- models/pool.go | 10 ---------- models/voucher_data_result.go | 7 ------- 2 files changed, 17 deletions(-) delete mode 100644 models/pool.go diff --git a/models/pool.go b/models/pool.go deleted file mode 100644 index 9e784b3..0000000 --- a/models/pool.go +++ /dev/null @@ -1,10 +0,0 @@ -package models - - -type Pool struct { - PoolName string `json:"poolName"` - PoolSymbol string `json:"poolSymbol"` - PoolContractAddress string `json:"poolContractAddress"` - LimiterAddress string `json:"limiterAddress"` - VoucherRegistry string `json:"voucherRegistry"` -} diff --git a/models/voucher_data_result.go b/models/voucher_data_result.go index 1311482..9a10831 100644 --- a/models/voucher_data_result.go +++ b/models/voucher_data_result.go @@ -8,10 +8,3 @@ type VoucherDataResult struct { TokenCommodity string `json:"tokenCommodity"` TokenLocation string `json:"tokenLocation"` } - -type SwappableVoucher struct { - ContractAddress string `json:"contractAddress"` - TokenSymbol string `json:"tokenSymbol"` - TokenDecimals string `json:"tokenDecimals"` - Balance string `json:"balance"` -} From e3b6c25792c21ec735286449afa0fc2afdc586d7 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 14:17:03 +0300 Subject: [PATCH 12/50] Added the swap functions to the accountService interface --- remote/account_service.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/remote/account_service.go b/remote/account_service.go index 2c67b12..ff9ec8f 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -17,4 +17,10 @@ type AccountService interface { TokenTransfer(ctx context.Context, amount, from, to, tokenAddress string) (*models.TokenTransferResponse, error) CheckAliasAddress(ctx context.Context, alias string) (*models.AliasAddress, error) RequestAlias(ctx context.Context, hint string, publicKey string) (*models.RequestAliasResult, error) + PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) + FetchTopPools(ctx context.Context, publicKey string) ([]dataserviceapi.PoolDetails, error) + GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) + PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) } From ba8d2a19c2edef703878062565d8bb50eccd3a3b Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 16:39:37 +0300 Subject: [PATCH 13/50] Use the DevAccountService functions to retrieve the data --- remote/http/service.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index 3792f5b..48bf678 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -298,11 +298,13 @@ func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from } func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { - return as.GetPoolSwappableFromVouchers(ctx, publicKey) + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.GetPoolSwappableFromVouchers(ctx, publicKey) } func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { - return as.GetPoolSwappableVouchers(ctx, publicKey) + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.GetPoolSwappableVouchers(ctx, publicKey) } func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { From d4f27af7a7ac71d48b33eb2d9385f66bca7650f4 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 7 Mar 2025 12:53:02 +0300 Subject: [PATCH 14/50] add check for account when doing a pool deposit --- dev/api.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/api.go b/dev/api.go index 5e9ca9b..749c99e 100644 --- a/dev/api.go +++ b/dev/api.go @@ -432,6 +432,11 @@ func (das *DevAccountService) CreateAccount(ctx context.Context) (*models.Accoun } func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { + _, ok := das.accounts[from] + if !ok { + return nil, fmt.Errorf("account not found (publickey): %v", from) + } + sym, ok := das.vouchersAddress[tokenAddress] if !ok { return nil, fmt.Errorf("voucher address %v not found", tokenAddress) From 37a2006a0b736d1c8f001f4173468680f03d64d3 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 10 Mar 2025 16:49:53 +0300 Subject: [PATCH 15/50] feat: persist and load pool info --- dev/api.go | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/dev/api.go b/dev/api.go index 749c99e..62c3cf1 100644 --- a/dev/api.go +++ b/dev/api.go @@ -34,6 +34,8 @@ const ( defaultDecimals = 6 zeroAddress string = "0x0000000000000000000000000000000000000000" defaultVoucherBalance float64 = 500.00 + cityPoolAddress string = "0x3b517308D858a47458aD5C8E699697C5dc91Da0F" + poolName string = "citypool" ) type Tx struct { @@ -92,6 +94,8 @@ type Voucher struct { } type Pool struct { + name string + address string vouchers []Voucher poolLimit map[string]string } @@ -124,7 +128,7 @@ func NewDevAccountService(ctx context.Context, ss storage.StorageService) *DevAc txs: make(map[string]Tx), txsTrack: make(map[string]string), autoVoucherValue: make(map[string]int), - pool: Pool{}, + pool: Pool{address: cityPoolAddress, name: poolName}, defaultAccount: zeroAddress, pfx: []byte("__"), } @@ -209,6 +213,20 @@ func (das *DevAccountService) loadAlias(ctx context.Context, alias string, key [ return nil } +func (das *DevAccountService) loadPoolInfo(ctx context.Context, name string, key []byte) error { + var pool Pool + poolB, err := das.db.Get(ctx, key) + if err != nil { + return err + } + err = json.Unmarshal(poolB, &pool) + if err != nil { + return fmt.Errorf("failed to unmarshall pool info: %v", err) + } + das.pool = pool + return nil +} + func (das *DevAccountService) loadItem(ctx context.Context, k []byte, v []byte) error { var err error s := string(k) @@ -225,6 +243,8 @@ func (das *DevAccountService) loadItem(ctx context.Context, k []byte, v []byte) } else if ss[0] == "alias" { err = das.loadAlias(ctx, ss[1], k) logg.ErrorCtxf(ctx, "loading aliases failed", "error_load_aliases", err) + } else if ss[0] == "pool" { + err = das.loadPoolInfo(ctx, ss[1], v) } else { logg.ErrorCtxf(ctx, "unknown double underscore key", "key", ss[0]) } @@ -361,6 +381,20 @@ func (das *DevAccountService) saveAccount(ctx context.Context, acc Account) erro return das.db.Put(ctx, []byte(k), v) } +func (das *DevAccountService) savePoolInfo(ctx context.Context, pool Pool) error { + if das.db == nil { + return nil + } + k := das.prefixKeyFor("pool", pool.name) + v, err := json.Marshal(pool) + if err != nil { + return err + } + das.db.SetSession("") + das.db.SetPrefix(db.DATATYPE_USERDATA) + return das.db.Put(ctx, []byte(k), v) +} + func (das *DevAccountService) saveAlias(ctx context.Context, alias map[string]string) error { if das.db == nil { return fmt.Errorf("Db cannot be nil") @@ -455,6 +489,7 @@ func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poo vouchers: append(das.pool.vouchers, voucher), poolLimit: map[string]string{tokenAddress: amount}, } + das.savePoolInfo(ctx, das.pool) return &models.PoolDepositResult{ TrackingId: uid.String(), }, nil From 3b39b86d09875c055be76390f7b05dee5d33c122 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 10 Mar 2025 17:12:05 +0300 Subject: [PATCH 16/50] pass the correct arguments to the swap functions --- dev/api.go | 6 +++--- remote/account_service.go | 6 +++--- remote/http/service.go | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/api.go b/dev/api.go index 62c3cf1..d469bc1 100644 --- a/dev/api.go +++ b/dev/api.go @@ -778,7 +778,7 @@ func (das *DevAccountService) RequestAlias(ctx context.Context, publicKey string }, nil } -func (das *DevAccountService) FetchTopPools(ctx context.Context, publicKey string) ([]dataserviceapi.PoolDetails, error) { +func (das *DevAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { topPools := []dataserviceapi.PoolDetails{ { PoolName: "Kenya ROLA Pool", @@ -820,7 +820,7 @@ func (das *DevAccountService) FetchTopPools(ctx context.Context, publicKey strin return topPools, nil } -func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { swapFromList := []dataserviceapi.TokenHoldings{ { ContractAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", @@ -851,7 +851,7 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, return swapFromList, nil } -func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { swapToList := []dataserviceapi.TokenHoldings{ { ContractAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", diff --git a/remote/account_service.go b/remote/account_service.go index ff9ec8f..fdb7021 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -18,9 +18,9 @@ type AccountService interface { CheckAliasAddress(ctx context.Context, alias string) (*models.AliasAddress, error) RequestAlias(ctx context.Context, hint string, publicKey string) (*models.RequestAliasResult, error) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) - FetchTopPools(ctx context.Context, publicKey string) ([]dataserviceapi.PoolDetails, error) - GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) - GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) + GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) + GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) } diff --git a/remote/http/service.go b/remote/http/service.go index 48bf678..2ee9a22 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -239,9 +239,9 @@ func resolveAliasAddress(ctx context.Context, alias string) (*models.AliasAddres return &r, err } -func (as *HTTPAccountService) FetchTopPools(ctx context.Context, publicKey string) ([]dataserviceapi.PoolDetails, error) { +func (as *HTTPAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { svc := dev.NewDevAccountService(ctx, as.SS) - return svc.FetchTopPools(ctx, publicKey) + return svc.FetchTopPools(ctx) } func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { @@ -297,14 +297,14 @@ func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from return &r, nil } -func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { svc := dev.NewDevAccountService(ctx, as.SS) - return svc.GetPoolSwappableFromVouchers(ctx, publicKey) + return svc.GetPoolSwappableFromVouchers(ctx, poolAddress, publicKey) } -func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { svc := dev.NewDevAccountService(ctx, as.SS) - return svc.GetPoolSwappableVouchers(ctx, publicKey) + return svc.GetPoolSwappableVouchers(ctx, poolAddress, publicKey) } func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { From 17e89e0b8828fc5a71a365586d7912b6418e5bdd Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 11 Mar 2025 15:46:17 +0300 Subject: [PATCH 17/50] Added the GetSwapFromTokenMaxLimit --- dev/api.go | 6 ++++++ remote/account_service.go | 1 + remote/http/service.go | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/dev/api.go b/dev/api.go index d469bc1..182db88 100644 --- a/dev/api.go +++ b/dev/api.go @@ -863,3 +863,9 @@ func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, pool return swapToList, nil } + +func (das *DevAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { + return &models.MaxLimitResult{ + Max: "1339482", + }, nil +} diff --git a/remote/account_service.go b/remote/account_service.go index fdb7021..cabd4d8 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -23,4 +23,5 @@ type AccountService interface { GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) + GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) } diff --git a/remote/http/service.go b/remote/http/service.go index 2ee9a22..a0bed1e 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -334,6 +334,11 @@ func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTo return &r, nil } +func (as *HTTPAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.GetSwapFromTokenMaxLimit(ctx, poolAddress, fromTokenAddress, toTokenAddress, publicKey) +} + // TODO: Use actual custodial api to request available alias func (as *HTTPAccountService) RequestAlias(ctx context.Context, publicKey string, hint string) (*models.RequestAliasResult, error) { if as.SS == nil { From 3244c717cbeea0ad25f279ca3b10a1d082bcc87c Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 11 Mar 2025 15:46:51 +0300 Subject: [PATCH 18/50] Added the MaxLimitResult struct model --- models/pool_swap_response.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/models/pool_swap_response.go b/models/pool_swap_response.go index 8842d67..35b2e12 100644 --- a/models/pool_swap_response.go +++ b/models/pool_swap_response.go @@ -12,3 +12,7 @@ type PoolSwapQuoteResult struct { type PoolSwapResult struct { TrackingId string `json:"trackingId"` } + +type MaxLimitResult struct { + Max string `json:"max"` +} From 5432365874375fa6829d78900c08a8234c88e4b0 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 12 Mar 2025 23:18:36 +0300 Subject: [PATCH 19/50] add logs,use same pool instance --- dev/api.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/api.go b/dev/api.go index 182db88..b07eb52 100644 --- a/dev/api.go +++ b/dev/api.go @@ -213,17 +213,15 @@ func (das *DevAccountService) loadAlias(ctx context.Context, alias string, key [ return nil } -func (das *DevAccountService) loadPoolInfo(ctx context.Context, name string, key []byte) error { +func (das *DevAccountService) loadPoolInfo(ctx context.Context, name string, v []byte) error { var pool Pool - poolB, err := das.db.Get(ctx, key) - if err != nil { - return err - } - err = json.Unmarshal(poolB, &pool) + + err := json.Unmarshal(v, &pool) if err != nil { return fmt.Errorf("failed to unmarshall pool info: %v", err) } das.pool = pool + logg.InfoCtxf(ctx, "loaded pool info", "name", das.pool.name, "vouchers", das.pool.vouchers) return nil } @@ -260,13 +258,13 @@ func (das *DevAccountService) loadAll(ctx context.Context) error { } for true { k, v := dumper.Next(ctx) + logg.InfoCtxf(ctx, "loading all", "key", string(k), "value", string(v)) if k == nil { break } if !bytes.HasPrefix(k, das.pfx) { continue } - err = das.loadItem(ctx, k, v) if err != nil { return err @@ -485,11 +483,13 @@ func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poo return nil, fmt.Errorf("voucher address %v found but does not resolve", tokenAddress) } - das.pool = Pool{ - vouchers: append(das.pool.vouchers, voucher), - poolLimit: map[string]string{tokenAddress: amount}, + das.pool.vouchers = append(das.pool.vouchers, voucher) + das.pool.poolLimit = map[string]string{tokenAddress: amount} + + err = das.savePoolInfo(ctx, das.pool) + if err != nil { + return nil, err } - das.savePoolInfo(ctx, das.pool) return &models.PoolDepositResult{ TrackingId: uid.String(), }, nil @@ -511,7 +511,7 @@ func (das *DevAccountService) GetPoolSwapQuote(ctx context.Context, amount, from if !p.hasVoucher(toTokenAddress) { return nil, fmt.Errorf("Voucher with address: %v not found in the pool", toTokenAddress) } - //Return a a quote that is equal to the amount enter + //Return a a quote that is equal to the amount entered return &models.PoolSwapQuoteResult{IncludesFeesDeduction: false, OutValue: amount}, nil } From 3c2889ac72f0f09abac7604a2a820081d8542cc7 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 10:05:49 +0300 Subject: [PATCH 20/50] Added pool swap functions to the TestAccountService --- testutil/testservice/account_service.go | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index 12b9de4..445fd9b 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -57,6 +57,10 @@ func (tas *TestAccountService) TokenTransfer(ctx context.Context, amount, from, }, nil } +func (m TestAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { + return &models.PoolDepositResult{}, nil +} + func (m TestAccountService) CheckAliasAddress(ctx context.Context, alias string) (*models.AliasAddress, error) { return &models.AliasAddress{}, nil } @@ -64,3 +68,27 @@ func (m TestAccountService) CheckAliasAddress(ctx context.Context, alias string) func (m TestAccountService) RequestAlias(ctx context.Context, publicKey string, hint string) (*models.RequestAliasResult, error) { return &models.RequestAliasResult{}, nil } + +func (m TestAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { + return []dataserviceapi.PoolDetails{}, nil +} + +func (m TestAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + return []dataserviceapi.TokenHoldings{}, nil +} + +func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + return []dataserviceapi.TokenHoldings{}, nil +} + +func (m TestAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { + return &models.PoolSwapQuoteResult{}, nil +} + +func (m TestAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { + return &models.PoolSwapResult{}, nil +} + +func (m TestAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { + return &models.MaxLimitResult{}, nil +} From ba43610ff00bec4eeb50078833badff2d1032f8b Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 13 Mar 2025 10:14:11 +0300 Subject: [PATCH 21/50] Added pool swap functions to the MockAccountService --- testutil/mocks/service_mock.go | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/testutil/mocks/service_mock.go b/testutil/mocks/service_mock.go index bfa9222..42bcb28 100644 --- a/testutil/mocks/service_mock.go +++ b/testutil/mocks/service_mock.go @@ -57,3 +57,38 @@ func (m MockAccountService) RequestAlias(ctx context.Context, publicKey string, args := m.Called(publicKey, hint) return args.Get(0).(*models.RequestAliasResult), args.Error(1) } + +func (m MockAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { + args := m.Called(amount, from, poolAddress, tokenAddress) + return args.Get(0).(*models.PoolDepositResult), args.Error(1) +} + +func (m MockAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { + args := m.Called() + return args.Get(0).([]dataserviceapi.PoolDetails), args.Error(1) +} + +func (m MockAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + args := m.Called(poolAddress, publicKey) + return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) +} + +func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + args := m.Called(poolAddress, publicKey) + return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) +} + +func (m MockAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { + args := m.Called(amount, from, fromTokenAddress, poolAddress, toTokenAddress) + return args.Get(0).(*models.PoolSwapQuoteResult), args.Error(1) +} + +func (m MockAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { + args := m.Called(amount, from, fromTokenAddress, poolAddress, toTokenAddress) + return args.Get(0).(*models.PoolSwapResult), args.Error(1) +} + +func (m MockAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { + args := m.Called(poolAddress, fromTokenAddress, toTokenAddress, publicKey) + return args.Get(0).(*models.MaxLimitResult), args.Error(1) +} From 06a7ddea6fcf14dd9bd9cafd61dfce26797579f0 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 13 Mar 2025 10:34:29 +0300 Subject: [PATCH 22/50] read persisted vouchers for a particular pool --- dev/api.go | 110 ++++++++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 74 deletions(-) diff --git a/dev/api.go b/dev/api.go index b07eb52..125aff3 100644 --- a/dev/api.go +++ b/dev/api.go @@ -36,6 +36,7 @@ const ( defaultVoucherBalance float64 = 500.00 cityPoolAddress string = "0x3b517308D858a47458aD5C8E699697C5dc91Da0F" poolName string = "citypool" + PoolSymbol string = "CTY" ) type Tx struct { @@ -94,10 +95,11 @@ type Voucher struct { } type Pool struct { - name string - address string - vouchers []Voucher - poolLimit map[string]string + Name string `json: "name"` + Symbol string `json: "symbol"` + Address string `json: "address"` + Vouchers []Voucher `json: "voucher"` + PoolLimit map[string]string `json: "poollimit"` } type DevAccountService struct { @@ -128,7 +130,7 @@ func NewDevAccountService(ctx context.Context, ss storage.StorageService) *DevAc txs: make(map[string]Tx), txsTrack: make(map[string]string), autoVoucherValue: make(map[string]int), - pool: Pool{address: cityPoolAddress, name: poolName}, + pool: Pool{Address: cityPoolAddress, Name: poolName}, defaultAccount: zeroAddress, pfx: []byte("__"), } @@ -183,7 +185,7 @@ func (das *DevAccountService) loadAccount(ctx context.Context, pubKey string, v } func (p *Pool) hasVoucher(voucherAddress string) bool { - for _, value := range p.vouchers { + for _, value := range p.Vouchers { if value.Address == voucherAddress { return true } @@ -221,7 +223,7 @@ func (das *DevAccountService) loadPoolInfo(ctx context.Context, name string, v [ return fmt.Errorf("failed to unmarshall pool info: %v", err) } das.pool = pool - logg.InfoCtxf(ctx, "loaded pool info", "name", das.pool.name, "vouchers", das.pool.vouchers) + logg.InfoCtxf(ctx, "loaded pool info", "name", das.pool.Name, "vouchers", das.pool.Vouchers) return nil } @@ -299,6 +301,12 @@ func (das *DevAccountService) WithAutoVoucher(ctx context.Context, symbol string return das } +func (das *DevAccountService) RegisterPool() { + das.pool.Name = poolName + das.pool.Address = cityPoolAddress + das.pool.Symbol = PoolSymbol +} + // TODO: add persistence for vouchers // TODO: set max balance for 0x00 address func (das *DevAccountService) AddVoucher(ctx context.Context, symbol string) error { @@ -383,7 +391,7 @@ func (das *DevAccountService) savePoolInfo(ctx context.Context, pool Pool) error if das.db == nil { return nil } - k := das.prefixKeyFor("pool", pool.name) + k := das.prefixKeyFor("pool", pool.Name) v, err := json.Marshal(pool) if err != nil { return err @@ -468,7 +476,6 @@ func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poo if !ok { return nil, fmt.Errorf("account not found (publickey): %v", from) } - sym, ok := das.vouchersAddress[tokenAddress] if !ok { return nil, fmt.Errorf("voucher address %v not found", tokenAddress) @@ -483,8 +490,8 @@ func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poo return nil, fmt.Errorf("voucher address %v found but does not resolve", tokenAddress) } - das.pool.vouchers = append(das.pool.vouchers, voucher) - das.pool.poolLimit = map[string]string{tokenAddress: amount} + das.pool.Vouchers = append(das.pool.Vouchers, voucher) + das.pool.PoolLimit = map[string]string{tokenAddress: amount} err = das.savePoolInfo(ctx, das.pool) if err != nil { @@ -779,75 +786,31 @@ func (das *DevAccountService) RequestAlias(ctx context.Context, publicKey string } func (das *DevAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { - topPools := []dataserviceapi.PoolDetails{ - { - PoolName: "Kenya ROLA Pool", - PoolSymbol: "ROLA", - PoolContractAdrress: "0x48a953cA5cf5298bc6f6Af3C608351f537AAcb9e", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "Nairobi ROLA Pool", - PoolSymbol: "NAIROBI", - PoolContractAdrress: "0xB0660Ac1Ee3d32ea35bc728D7CA1705Fa5A37528", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "Friends of Kiriba Ecosystem", - PoolSymbol: "FRIENDS", - PoolContractAdrress: "0xC4848263821FA02baB2181910A2eFb9CECb2c21C", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "Resilient Community Waqfs", - PoolSymbol: "REZILIENS", - PoolContractAdrress: "0x1e40951d7a28147D8B4A554C60c42766C92e2Fc6", - LimiterAddress: "", - VoucherRegistry: "", - }, - { - PoolName: "GrE Tech", - PoolSymbol: "GRET", - PoolContractAdrress: "0xb7B9d0A264eD1a8E2418571B7AC5933C79C9c2B8", - LimiterAddress: "", - VoucherRegistry: "", - }, + var topPools []dataserviceapi.PoolDetails + + pool := dataserviceapi.PoolDetails{ + PoolName: das.pool.Name, + PoolSymbol: das.pool.Symbol, + PoolContractAdrress: das.pool.Address, } + // Add the citypool as the main pool + topPools = append(topPools, pool) + return topPools, nil } func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { - swapFromList := []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0xc7B78Ac9ACB9E025C8234621FC515bC58179dEAe", - TokenSymbol: "AMANI", - TokenDecimals: "6", - Balance: "", - }, - { - ContractAddress: "0xF0C3C7581b8b96B59a97daEc8Bd48247cE078674", - TokenSymbol: "AMUA", - TokenDecimals: "6", - Balance: "", - }, - { - ContractAddress: "0x371455a30fc62736145Bd8429Fcc6481186f235F", - TokenSymbol: "BAHARI", - TokenDecimals: "6", - Balance: "", - }, - { - ContractAddress: "0x7cA6113b59c24a880F382C7E12d609a6Eb05246b", - TokenSymbol: "BANGLA", - TokenDecimals: "6", - Balance: "", - }, - } + var swapFromList []dataserviceapi.TokenHoldings + for _, voucher := range das.pool.Vouchers { + swapFromList = append(swapFromList, dataserviceapi.TokenHoldings{ + ContractAddress: voucher.Address, + TokenSymbol: voucher.Symbol, + TokenDecimals: string(defaultDecimals), + Balance: fmt.Sprintf("%f", defaultVoucherBalance), + }) + } return swapFromList, nil } @@ -860,7 +823,6 @@ func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, pool Balance: "", }, } - return swapToList, nil } From e053d561c9aba0f07e218bcd990d1eae9fc042fa Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 14 Mar 2025 10:04:04 +0300 Subject: [PATCH 23/50] feat(pool): add multiple pools --- dev/api.go | 135 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/dev/api.go b/dev/api.go index 125aff3..c3ac5e7 100644 --- a/dev/api.go +++ b/dev/api.go @@ -117,7 +117,7 @@ type DevAccountService struct { defaultAccount string emitterFunc event.EmitterFunc pfx []byte - pool Pool + pools map[string]Pool } func NewDevAccountService(ctx context.Context, ss storage.StorageService) *DevAccountService { @@ -130,7 +130,7 @@ func NewDevAccountService(ctx context.Context, ss storage.StorageService) *DevAc txs: make(map[string]Tx), txsTrack: make(map[string]string), autoVoucherValue: make(map[string]int), - pool: Pool{Address: cityPoolAddress, Name: poolName}, + pools: make(map[string]Pool), defaultAccount: zeroAddress, pfx: []byte("__"), } @@ -222,8 +222,7 @@ func (das *DevAccountService) loadPoolInfo(ctx context.Context, name string, v [ if err != nil { return fmt.Errorf("failed to unmarshall pool info: %v", err) } - das.pool = pool - logg.InfoCtxf(ctx, "loaded pool info", "name", das.pool.Name, "vouchers", das.pool.Vouchers) + das.pools[name] = pool return nil } @@ -234,6 +233,7 @@ func (das *DevAccountService) loadItem(ctx context.Context, k []byte, v []byte) if len(ss) != 2 { return fmt.Errorf("malformed key: %s", s) } + fmt.Println("S1", ss[0]) if ss[0] == "account" { err = das.loadAccount(ctx, ss[1], v) logg.ErrorCtxf(ctx, "loading saved account failed", "error_load_account", err) @@ -301,10 +301,29 @@ func (das *DevAccountService) WithAutoVoucher(ctx context.Context, symbol string return das } -func (das *DevAccountService) RegisterPool() { - das.pool.Name = poolName - das.pool.Address = cityPoolAddress - das.pool.Symbol = PoolSymbol +func (das *DevAccountService) RegisterPool(ctx context.Context, name string, sm string) error { + var seedVouchers []Voucher + + h := sha1.New() + h.Write([]byte(sm)) + z := h.Sum(nil) + pooladdr := fmt.Sprintf("0x%x", z) + + for _, v := range das.vouchers { + //pre-load vouchers with vouchers when a pool is registered + seedVouchers = append(seedVouchers, v) + } + p := Pool{ + Name: name, + Symbol: sm, + Address: pooladdr, + Vouchers: seedVouchers, + } + err := das.savePoolInfo(ctx, p) + if err != nil { + return err + } + return nil } // TODO: add persistence for vouchers @@ -391,7 +410,7 @@ func (das *DevAccountService) savePoolInfo(ctx context.Context, pool Pool) error if das.db == nil { return nil } - k := das.prefixKeyFor("pool", pool.Name) + k := das.prefixKeyFor("pool", pool.Address) v, err := json.Marshal(pool) if err != nil { return err @@ -485,15 +504,15 @@ func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poo return nil, err } - voucher, ok := das.vouchers[sym] + _, ok = das.vouchers[sym] if !ok { return nil, fmt.Errorf("voucher address %v found but does not resolve", tokenAddress) } - das.pool.Vouchers = append(das.pool.Vouchers, voucher) - das.pool.PoolLimit = map[string]string{tokenAddress: amount} + // das.pool.Vouchers = append(das.pool.Vouchers, voucher) + // das.pool.PoolLimit = map[string]string{tokenAddress: amount} - err = das.savePoolInfo(ctx, das.pool) + // err = das.savePoolInfo(ctx, das.pool) if err != nil { return nil, err } @@ -507,17 +526,17 @@ func (das *DevAccountService) GetPoolSwapQuote(ctx context.Context, amount, from if !ok { return nil, fmt.Errorf("account not found (publickey): %v", from) } + _, ok = das.pools[poolAddress] + if !ok { + return nil, fmt.Errorf("pool address %v not found", poolAddress) + } + //resolve the token address you are trying to swap from(fromTokenAddress) _, ok = das.vouchersAddress[fromTokenAddress] if !ok { return nil, fmt.Errorf("voucher address %v not found", fromTokenAddress) } - p := das.pool - //check if pool has voucher to swap to - if !p.hasVoucher(toTokenAddress) { - return nil, fmt.Errorf("Voucher with address: %v not found in the pool", toTokenAddress) - } //Return a a quote that is equal to the amount entered return &models.PoolSwapQuoteResult{IncludesFeesDeduction: false, OutValue: amount}, nil } @@ -528,19 +547,22 @@ func (das *DevAccountService) PoolSwap(ctx context.Context, amount, from, fromTo return nil, err } - _, ok := das.accounts[from] + p, ok := das.pools[poolAddress] + if !ok { + return nil, fmt.Errorf("pool address %v not found", toTokenAddress) + } + _, ok = das.accounts[from] if !ok { return nil, fmt.Errorf("account not found (publickey): %v", from) } - _, ok = das.vouchersAddress[fromTokenAddress] + ok = p.hasVoucher(fromTokenAddress) if !ok { - return nil, fmt.Errorf("voucher address %v not found", fromTokenAddress) + return nil, fmt.Errorf("token %v not found in the pool", fromTokenAddress) } - p := das.pool - //check if pool has voucher to swap to - if !p.hasVoucher(toTokenAddress) { - return nil, fmt.Errorf("Voucher with address: %v not found in the pool", toTokenAddress) + ok = p.hasVoucher(toTokenAddress) + if !ok { + return nil, fmt.Errorf("token %v not found in the pool", toTokenAddress) } return &models.PoolSwapResult{TrackingId: uid.String()}, nil @@ -787,47 +809,64 @@ func (das *DevAccountService) RequestAlias(ctx context.Context, publicKey string func (das *DevAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { var topPools []dataserviceapi.PoolDetails - - pool := dataserviceapi.PoolDetails{ - PoolName: das.pool.Name, - PoolSymbol: das.pool.Symbol, - PoolContractAdrress: das.pool.Address, + for _, p := range das.pools { + topPools = append(topPools, dataserviceapi.PoolDetails{ + PoolName: p.Name, + PoolSymbol: p.Symbol, + PoolContractAdrress: p.Address, + }) } - - // Add the citypool as the main pool - topPools = append(topPools, pool) - return topPools, nil } func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { var swapFromList []dataserviceapi.TokenHoldings - for _, voucher := range das.pool.Vouchers { + p, ok := das.pools[poolAddress] + if !ok { + return nil, fmt.Errorf("Invalid pool address: %v", poolAddress) + } + for _, v := range p.Vouchers { swapFromList = append(swapFromList, dataserviceapi.TokenHoldings{ + ContractAddress: v.Address, + TokenSymbol: v.Symbol, + TokenDecimals: string(defaultDecimals), + Balance: fmt.Sprintf("%f", defaultVoucherBalance), + }) + } + + return swapFromList, nil +} + +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + var swapToList []dataserviceapi.TokenHoldings + _, ok := das.pools[poolAddress] + if !ok { + return nil, fmt.Errorf("Invalid pool address: %v", poolAddress) + } + for _, voucher := range das.vouchers { + swapToList = append(swapToList, dataserviceapi.TokenHoldings{ ContractAddress: voucher.Address, TokenSymbol: voucher.Symbol, TokenDecimals: string(defaultDecimals), Balance: fmt.Sprintf("%f", defaultVoucherBalance), }) } - return swapFromList, nil -} - -func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { - swapToList := []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0x765DE816845861e75A25fCA122bb6898B8B1282a", - TokenSymbol: "cUSD", - TokenDecimals: "18", - Balance: "", - }, - } return swapToList, nil } func (das *DevAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { + + p, ok := das.pools[poolAddress] + if !ok { + return nil, fmt.Errorf("Pool address: %v not found ", poolAddress) + } + limit, ok := p.PoolLimit[fromTokenAddress] + if !ok { + return nil, fmt.Errorf("Token address: %v not found in the pool", fromTokenAddress) + } + return &models.MaxLimitResult{ - Max: "1339482", + Max: limit, }, nil } From c09cb77e196c81bca1ad1fa4df174f3b34e530ba Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 17 Mar 2025 12:08:17 +0300 Subject: [PATCH 24/50] implement pool limit --- dev/api.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dev/api.go b/dev/api.go index c3ac5e7..2905cc5 100644 --- a/dev/api.go +++ b/dev/api.go @@ -309,16 +309,20 @@ func (das *DevAccountService) RegisterPool(ctx context.Context, name string, sm z := h.Sum(nil) pooladdr := fmt.Sprintf("0x%x", z) + p := Pool{ + Name: name, + Symbol: sm, + Address: pooladdr, + PoolLimit: make(map[string]string), + } + for _, v := range das.vouchers { //pre-load vouchers with vouchers when a pool is registered seedVouchers = append(seedVouchers, v) + p.PoolLimit[v.Address] = fmt.Sprintf("%f", defaultVoucherBalance) } - p := Pool{ - Name: name, - Symbol: sm, - Address: pooladdr, - Vouchers: seedVouchers, - } + p.Vouchers = append(p.Vouchers, seedVouchers...) + err := das.savePoolInfo(ctx, p) if err != nil { return err @@ -509,10 +513,6 @@ func (das *DevAccountService) PoolDeposit(ctx context.Context, amount, from, poo return nil, fmt.Errorf("voucher address %v found but does not resolve", tokenAddress) } - // das.pool.Vouchers = append(das.pool.Vouchers, voucher) - // das.pool.PoolLimit = map[string]string{tokenAddress: amount} - - // err = das.savePoolInfo(ctx, das.pool) if err != nil { return nil, err } @@ -526,15 +526,15 @@ func (das *DevAccountService) GetPoolSwapQuote(ctx context.Context, amount, from if !ok { return nil, fmt.Errorf("account not found (publickey): %v", from) } - _, ok = das.pools[poolAddress] + p, ok := das.pools[poolAddress] if !ok { return nil, fmt.Errorf("pool address %v not found", poolAddress) } //resolve the token address you are trying to swap from(fromTokenAddress) - _, ok = das.vouchersAddress[fromTokenAddress] + ok = p.hasVoucher(fromTokenAddress) if !ok { - return nil, fmt.Errorf("voucher address %v not found", fromTokenAddress) + return nil, fmt.Errorf("voucher with address %v not found in the pool", fromTokenAddress) } //Return a a quote that is equal to the amount entered From ee04552cbbe59d3c54be00aaf2fcf6a462d44870 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 17 Mar 2025 20:40:19 +0300 Subject: [PATCH 25/50] feat: implement fetch top pools,retrieve pool details using a pool symbol --- remote/http/service.go | 43 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/remote/http/service.go b/remote/http/service.go index a0bed1e..afec1d7 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -241,7 +241,48 @@ func resolveAliasAddress(ctx context.Context, alias string) (*models.AliasAddres func (as *HTTPAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { svc := dev.NewDevAccountService(ctx, as.SS) - return svc.FetchTopPools(ctx) + if as.UseApi { + return fetchCustodialTopPools(ctx) + } else { + return svc.FetchTopPools(ctx) + } +} + +func fetchCustodialTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { + var r struct { + TopPools []dataserviceapi.PoolDetails `json:"topPools"` + } + + req, err := http.NewRequest("GET", config.TopPoolsURL, nil) + if err != nil { + return nil, err + } + + _, err = doRequest(ctx, req, &r) + return r.TopPools, nil +} + +func (as *HTTPAccountService) RetrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) { + if as.UseApi { + return retrievePoolDetails(ctx, sym) + } else { + return nil, nil + } +} + +func retrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) { + var r dataserviceapi.PoolDetails + + ep, err := url.JoinPath(config.RetrievePoolDetailsURL, sym) + if err != nil { + return nil, err + } + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + return &r, nil } func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { From 720fa94b56d858788f0dd379d6083e9d68ac8d56 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 17 Mar 2025 20:40:56 +0300 Subject: [PATCH 26/50] register pool endpoints --- config/config.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/config/config.go b/config/config.go index c9f323e..3cede70 100644 --- a/config/config.go +++ b/config/config.go @@ -19,6 +19,8 @@ const ( poolDepositPrefix = "/api/v2/pool/deposit" poolSwapQoutePrefix = "/api/v2/pool/quote" poolSwapPrefix = "/api/v2/pool/swap" + topPoolsPrefix = "/api/v1/pool/top" + retrievePoolDetailsPrefix = "/api/v1/pool/reverse" ) var ( @@ -28,18 +30,20 @@ var ( ) var ( - CreateAccountURL string - TrackStatusURL string - BalanceURL string - TrackURL string - TokenTransferURL string - VoucherHoldingsURL string - VoucherTransfersURL string - VoucherDataURL string - CheckAliasURL string - PoolDepositURL string - PoolSwapQuoteURL string - PoolSwapURL string + CreateAccountURL string + TrackStatusURL string + BalanceURL string + TrackURL string + TokenTransferURL string + VoucherHoldingsURL string + VoucherTransfersURL string + VoucherDataURL string + CheckAliasURL string + PoolDepositURL string + PoolSwapQuoteURL string + PoolSwapURL string + TopPoolsURL string + RetrievePoolDetailsURL string ) func setBase() error { @@ -78,6 +82,8 @@ func LoadConfig() error { PoolDepositURL, _ = url.JoinPath(custodialURLBase, poolDepositPrefix) PoolSwapQuoteURL, _ = url.JoinPath(custodialURLBase, poolSwapQoutePrefix) PoolSwapURL, _ = url.JoinPath(custodialURLBase, poolSwapPrefix) + TopPoolsURL, _ = url.JoinPath(dataURLBase, topPoolsPrefix) + RetrievePoolDetailsURL, _ = url.JoinPath(dataURLBase, retrievePoolDetailsPrefix) return nil } From 4444ac0255e8bf48894ace48e240012a92d4b1b5 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 19 Mar 2025 12:07:11 +0300 Subject: [PATCH 27/50] add pool swap endpoints --- config/config.go | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/config/config.go b/config/config.go index 3cede70..5890594 100644 --- a/config/config.go +++ b/config/config.go @@ -19,8 +19,9 @@ const ( poolDepositPrefix = "/api/v2/pool/deposit" poolSwapQoutePrefix = "/api/v2/pool/quote" poolSwapPrefix = "/api/v2/pool/swap" - topPoolsPrefix = "/api/v1/pool/top" - retrievePoolDetailsPrefix = "/api/v1/pool/reverse" + topPoolsPrefix = "/api/v1/pool/top" + retrievePoolDetailsPrefix = "/api/v1/pool/reverse" + poolSwappableVouchersPrefix = "/api/v1/pool" ) var ( @@ -30,20 +31,21 @@ var ( ) var ( - CreateAccountURL string - TrackStatusURL string - BalanceURL string - TrackURL string - TokenTransferURL string - VoucherHoldingsURL string - VoucherTransfersURL string - VoucherDataURL string - CheckAliasURL string - PoolDepositURL string - PoolSwapQuoteURL string - PoolSwapURL string - TopPoolsURL string - RetrievePoolDetailsURL string + CreateAccountURL string + TrackStatusURL string + BalanceURL string + TrackURL string + TokenTransferURL string + VoucherHoldingsURL string + VoucherTransfersURL string + VoucherDataURL string + CheckAliasURL string + PoolDepositURL string + PoolSwapQuoteURL string + PoolSwapURL string + TopPoolsURL string + RetrievePoolDetailsURL string + PoolSwappableVouchersURL string ) func setBase() error { @@ -84,6 +86,7 @@ func LoadConfig() error { PoolSwapURL, _ = url.JoinPath(custodialURLBase, poolSwapPrefix) TopPoolsURL, _ = url.JoinPath(dataURLBase, topPoolsPrefix) RetrievePoolDetailsURL, _ = url.JoinPath(dataURLBase, retrievePoolDetailsPrefix) + PoolSwappableVouchersURL, _ = url.JoinPath(dataURLBase, poolSwappableVouchersPrefix) return nil } From 80c2493e803b75829196201214d47208ab427ca2 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 19 Mar 2025 12:09:52 +0300 Subject: [PATCH 28/50] implement get token pool limit,get all pool swappable vouchers --- remote/http/service.go | 75 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index afec1d7..2346eef 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -339,13 +339,56 @@ func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from } func (as *HTTPAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { - svc := dev.NewDevAccountService(ctx, as.SS) - return svc.GetPoolSwappableFromVouchers(ctx, poolAddress, publicKey) + if as.UseApi { + return as.getPoolSwappableFromVouchers(ctx, poolAddress, publicKey) + } else { + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.GetPoolSwappableFromVouchers(ctx, poolAddress, publicKey) + } + +} + +func (as *HTTPAccountService) getPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + var r struct { + PoolSwappableVouchers []dataserviceapi.TokenHoldings `json:"filtered"` + } + ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "from", publicKey) + if err != nil { + return nil, err + } + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + + return r.PoolSwappableVouchers, nil } func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { svc := dev.NewDevAccountService(ctx, as.SS) - return svc.GetPoolSwappableVouchers(ctx, poolAddress, publicKey) + if as.UseApi { + return as.getPoolSwappableFromVouchers(ctx, poolAddress, publicKey) + } else { + return svc.GetPoolSwappableVouchers(ctx, poolAddress, publicKey) + } +} + +func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + var r struct { + PoolSwappableVouchers []dataserviceapi.TokenHoldings `json:"filtered"` + } + + ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to", publicKey) + if err != nil { + return nil, err + } + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + return r.PoolSwappableVouchers, nil } func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) { @@ -376,8 +419,30 @@ func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTo } func (as *HTTPAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { - svc := dev.NewDevAccountService(ctx, as.SS) - return svc.GetSwapFromTokenMaxLimit(ctx, poolAddress, fromTokenAddress, toTokenAddress, publicKey) + if as.UseApi { + return as.getSwapFromTokenMaxLimit(ctx, poolAddress, fromTokenAddress, toTokenAddress, publicKey) + } else { + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.GetSwapFromTokenMaxLimit(ctx, poolAddress, fromTokenAddress, toTokenAddress, publicKey) + } +} + +func (as *HTTPAccountService) getSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokeAddress, publicKey string) (*models.MaxLimitResult, error) { + var r struct { + MaxPoolLimitResult models.MaxLimitResult `json:"max"` + } + + ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "limit", fromTokenAddress, toTokeAddress, publicKey) + if err != nil { + return nil, err + } + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + + return &r.MaxPoolLimitResult, nil } // TODO: Use actual custodial api to request available alias From 8b2bd7214316d275301167701357b0e80ab2cdca Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 17 May 2025 14:35:53 +0300 Subject: [PATCH 29/50] format document --- config/config.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/config/config.go b/config/config.go index a9221aa..080d627 100644 --- a/config/config.go +++ b/config/config.go @@ -7,24 +7,24 @@ import ( ) const ( - createAccountPath = "/api/v2/account/create" - trackStatusPath = "/api/track" - balancePathPrefix = "/api/account" - trackPath = "/api/v2/account/status" - tokenTransferPrefix = "/api/v2/token/transfer" - voucherHoldingsPathPrefix = "/api/v1/holdings" - voucherTransfersPathPrefix = "/api/v1/transfers/last10" - voucherDataPathPrefix = "/api/v1/token" - aliasPrefix = "api/v1/alias" - SendSMSPrefix = "api/v1/external/upsell" - poolDepositPrefix = "/api/v2/pool/deposit" - poolSwapQoutePrefix = "/api/v2/pool/quote" - poolSwapPrefix = "/api/v2/pool/swap" + createAccountPath = "/api/v2/account/create" + trackStatusPath = "/api/track" + balancePathPrefix = "/api/account" + trackPath = "/api/v2/account/status" + tokenTransferPrefix = "/api/v2/token/transfer" + voucherHoldingsPathPrefix = "/api/v1/holdings" + voucherTransfersPathPrefix = "/api/v1/transfers/last10" + voucherDataPathPrefix = "/api/v1/token" + aliasPrefix = "api/v1/alias" + SendSMSPrefix = "api/v1/external/upsell" + poolDepositPrefix = "/api/v2/pool/deposit" + poolSwapQoutePrefix = "/api/v2/pool/quote" + poolSwapPrefix = "/api/v2/pool/swap" topPoolsPrefix = "/api/v1/pool/top" retrievePoolDetailsPrefix = "/api/v1/pool/reverse" poolSwappableVouchersPrefix = "/api/v1/pool" - AliasEnsPrefix = "/api/v1/bypass" - ExternalSMSPrefix = "/api/v1/external" + AliasEnsPrefix = "/api/v1/bypass" + ExternalSMSPrefix = "/api/v1/external" ) var ( @@ -51,9 +51,9 @@ var ( TopPoolsURL string RetrievePoolDetailsURL string PoolSwappableVouchersURL string - SendSMSURL string - AliasEnsURL string - ExternalSMSURL string + SendSMSURL string + AliasEnsURL string + ExternalSMSURL string ) func setBase() error { From f101ffd4c93ef1edb8bc72496cbf1c702d612c00 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 17 May 2025 14:36:26 +0300 Subject: [PATCH 30/50] added a model for TokenInPoolResult --- models/pool_swap_response.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/models/pool_swap_response.go b/models/pool_swap_response.go index 35b2e12..4f2c088 100644 --- a/models/pool_swap_response.go +++ b/models/pool_swap_response.go @@ -16,3 +16,7 @@ type PoolSwapResult struct { type MaxLimitResult struct { Max string `json:"max"` } + +type TokenInPoolResult struct { + CanSwapFrom bool `json:"canSwapFrom"` +} From ee434dba69805dd3cac368a2b4870cf12c5372bd Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 17 May 2025 14:37:06 +0300 Subject: [PATCH 31/50] added CheckTokenInPool to check whether a token can be swapped from in a pool --- dev/api.go | 7 ++++++- remote/http/service.go | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/dev/api.go b/dev/api.go index d879869..43e525b 100644 --- a/dev/api.go +++ b/dev/api.go @@ -870,7 +870,6 @@ func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, pool } func (das *DevAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { - p, ok := das.pools[poolAddress] if !ok { return nil, fmt.Errorf("Pool address: %v not found ", poolAddress) @@ -884,3 +883,9 @@ func (das *DevAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, pool Max: limit, }, nil } + +func (das *DevAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { + return &models.TokenInPoolResult{ + CanSwapFrom: true, + }, nil +} diff --git a/remote/http/service.go b/remote/http/service.go index d69b5ae..c8431b0 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -469,6 +469,33 @@ func (as *HTTPAccountService) getSwapFromTokenMaxLimit(ctx context.Context, pool return &r.MaxPoolLimitResult, nil } +func (as *HTTPAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { + if as.UseApi { + return as.checkTokenInPool(ctx, poolAddress, tokenAddress) + } else { + svc := dev.NewDevAccountService(ctx, as.SS) + return svc.CheckTokenInPool(ctx, poolAddress, tokenAddress) + } +} + +func (as *HTTPAccountService) checkTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { + var r struct { + TokenInPoolResult models.TokenInPoolResult `json:"canSwapFrom"` + } + + ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "check", tokenAddress) + if err != nil { + return nil, err + } + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) + + return &r.TokenInPoolResult, nil +} + // TODO: Use actual custodial api to request available alias func (as *HTTPAccountService) RequestAlias(ctx context.Context, publicKey string, hint string) (*models.RequestAliasResult, error) { if as.SS == nil { From 050998ff82b1cfb91b3526c48d6dae0e807f8cab Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 17 May 2025 14:45:12 +0300 Subject: [PATCH 32/50] added CheckTokenInPool to the account_service and test utils --- remote/account_service.go | 1 + testutil/mocks/service_mock.go | 5 +++++ testutil/testservice/account_service.go | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/remote/account_service.go b/remote/account_service.go index 1ea0af7..5bf65a8 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -27,4 +27,5 @@ type AccountService interface { GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) + CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) } diff --git a/testutil/mocks/service_mock.go b/testutil/mocks/service_mock.go index aaa78bb..de19d54 100644 --- a/testutil/mocks/service_mock.go +++ b/testutil/mocks/service_mock.go @@ -105,3 +105,8 @@ func (m MockAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAd args := m.Called(poolAddress, fromTokenAddress, toTokenAddress, publicKey) return args.Get(0).(*models.MaxLimitResult), args.Error(1) } + +func (m MockAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { + args := m.Called(poolAddress, tokenAddress) + return args.Get(0).(*models.TokenInPoolResult), args.Error(1) +} diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index 00906c0..46abb1a 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -104,3 +104,7 @@ func (m TestAccountService) PoolSwap(ctx context.Context, amount, from, fromToke func (m TestAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) { return &models.MaxLimitResult{}, nil } + +func (m TestAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { + return &models.TokenInPoolResult{}, nil +} From e6677015d90777e6e330421ffcfc0dd6067aac96 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 19 May 2025 10:36:47 +0300 Subject: [PATCH 33/50] use the latest ussd-data-service --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4b25b5f..c1f6922 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta - github.com/grassrootseconomics/ussd-data-service v1.4.0-beta + github.com/grassrootseconomics/ussd-data-service v1.4.4-beta github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 6653efe..857291f 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/grassrootseconomics/ussd-data-service v1.2.0-beta h1:fn1gwbWIwHVEBtUC github.com/grassrootseconomics/ussd-data-service v1.2.0-beta/go.mod h1:omfI0QtUwIdpu9gMcUqLMCG8O1XWjqJGBx1qUMiGWC0= github.com/grassrootseconomics/ussd-data-service v1.4.0-beta h1:4fMd/3h2ZIhRg4GdHQmRw5FfD3MpJvFNNJQo+Q27f5M= github.com/grassrootseconomics/ussd-data-service v1.4.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= +github.com/grassrootseconomics/ussd-data-service v1.4.4-beta h1:turlyo0i3OLj29mWpWNoB/3Qao8qEngT/5d1jDWTZE4= +github.com/grassrootseconomics/ussd-data-service v1.4.4-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= From 334aa07f9f4dc1849d0d00d6451c1a1cffd6d805 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 20 May 2025 15:48:13 +0300 Subject: [PATCH 34/50] Fix: Correct JSON mapping for checkTokenInPool and getSwapFromTokenMaxLimit API responses --- remote/http/service.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index c8431b0..b7d49a5 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -452,9 +452,7 @@ func (as *HTTPAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, pool } func (as *HTTPAccountService) getSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokeAddress, publicKey string) (*models.MaxLimitResult, error) { - var r struct { - MaxPoolLimitResult models.MaxLimitResult `json:"max"` - } + var r models.MaxLimitResult ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "limit", fromTokenAddress, toTokeAddress, publicKey) if err != nil { @@ -465,8 +463,11 @@ func (as *HTTPAccountService) getSwapFromTokenMaxLimit(ctx context.Context, pool return nil, err } _, err = doRequest(ctx, req, &r) + if err != nil { + return nil, err + } - return &r.MaxPoolLimitResult, nil + return &r, nil } func (as *HTTPAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { @@ -479,9 +480,7 @@ func (as *HTTPAccountService) CheckTokenInPool(ctx context.Context, poolAddress, } func (as *HTTPAccountService) checkTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) { - var r struct { - TokenInPoolResult models.TokenInPoolResult `json:"canSwapFrom"` - } + var r models.TokenInPoolResult ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "check", tokenAddress) if err != nil { @@ -492,8 +491,11 @@ func (as *HTTPAccountService) checkTokenInPool(ctx context.Context, poolAddress, return nil, err } _, err = doRequest(ctx, req, &r) + if err != nil { + return nil, err + } - return &r.TokenInPoolResult, nil + return &r, nil } // TODO: Use actual custodial api to request available alias From 81fbc2574c30a6884b5395bc3fcff498d87ab6c9 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 20 May 2025 15:50:35 +0300 Subject: [PATCH 35/50] Fix: use the correct getPoolSwappableVouchers --- remote/http/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remote/http/service.go b/remote/http/service.go index b7d49a5..10b27f2 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -392,7 +392,7 @@ func (as *HTTPAccountService) getPoolSwappableFromVouchers(ctx context.Context, func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { svc := dev.NewDevAccountService(ctx, as.SS) if as.UseApi { - return as.getPoolSwappableFromVouchers(ctx, poolAddress, publicKey) + return as.getPoolSwappableVouchers(ctx, poolAddress, publicKey) } else { return svc.GetPoolSwappableVouchers(ctx, poolAddress, publicKey) } From f234d511047d92e66f9e745753558ac2fdf2b1dc Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 21 May 2025 15:21:27 +0300 Subject: [PATCH 36/50] Fix: update the getPoolSwappableVouchers to pass a 'stable' query parameter --- remote/http/service.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index 10b27f2..612a93b 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -389,28 +389,38 @@ func (as *HTTPAccountService) getPoolSwappableFromVouchers(ctx context.Context, return r.PoolSwappableVouchers, nil } -func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { svc := dev.NewDevAccountService(ctx, as.SS) if as.UseApi { - return as.getPoolSwappableVouchers(ctx, poolAddress, publicKey) + return as.getPoolSwappableVouchers(ctx, poolAddress) } else { - return svc.GetPoolSwappableVouchers(ctx, poolAddress, publicKey) + return svc.GetPoolSwappableVouchers(ctx, poolAddress) } } -func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { var r struct { PoolSwappableVouchers []dataserviceapi.TokenHoldings `json:"filtered"` } - ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to", publicKey) + ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to") if err != nil { return nil, err } - req, err := http.NewRequest("GET", ep, nil) + u, err := url.Parse(ep) if err != nil { return nil, err } + + query := u.Query() + query.Set("stable", "true") + u.RawQuery = query.Encode() + + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, err + } + _, err = doRequest(ctx, req, &r) return r.PoolSwappableVouchers, nil } From 857f564aae7bc94872790a6f35bbb2e663b0cd82 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 21 May 2025 15:22:31 +0300 Subject: [PATCH 37/50] Fix: remove the unused publicKey from the GetPoolSwappableVouchers --- dev/api.go | 2 +- remote/account_service.go | 2 +- testutil/mocks/service_mock.go | 4 ++-- testutil/testservice/account_service.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/api.go b/dev/api.go index 43e525b..00e14d8 100644 --- a/dev/api.go +++ b/dev/api.go @@ -852,7 +852,7 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, return swapFromList, nil } -func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { var swapToList []dataserviceapi.TokenHoldings _, ok := das.pools[poolAddress] if !ok { diff --git a/remote/account_service.go b/remote/account_service.go index 5bf65a8..4050295 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -23,7 +23,7 @@ type AccountService interface { PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) - GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) + GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) diff --git a/testutil/mocks/service_mock.go b/testutil/mocks/service_mock.go index de19d54..1c0ee97 100644 --- a/testutil/mocks/service_mock.go +++ b/testutil/mocks/service_mock.go @@ -86,8 +86,8 @@ func (m MockAccountService) GetPoolSwappableFromVouchers(ctx context.Context, po return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } -func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { - args := m.Called(poolAddress, publicKey) +func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { + args := m.Called(poolAddress) return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index 46abb1a..f9c69ef 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -89,7 +89,7 @@ func (m TestAccountService) GetPoolSwappableFromVouchers(ctx context.Context, po return []dataserviceapi.TokenHoldings{}, nil } -func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { +func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { return []dataserviceapi.TokenHoldings{}, nil } From a354371a9470529b79fc6f81b2473bdbcdf96f91 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 21 May 2025 15:40:56 +0300 Subject: [PATCH 38/50] add the IncludeStablesParam config --- config/config.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/config/config.go b/config/config.go index 080d627..f9a2e37 100644 --- a/config/config.go +++ b/config/config.go @@ -28,11 +28,12 @@ const ( ) var ( - custodialURLBase string - dataURLBase string - BearerToken string - aliasEnsURLBase string - externalSMSBase string + custodialURLBase string + dataURLBase string + BearerToken string + aliasEnsURLBase string + externalSMSBase string + IncludeStablesParam string ) var ( @@ -64,6 +65,7 @@ func setBase() error { aliasEnsURLBase = env.GetEnv("ALIAS_ENS_BASE", "http://localhost:5015") externalSMSBase = env.GetEnv("EXTERNAL_SMS_BASE", "http://localhost:5035") BearerToken = env.GetEnv("BEARER_TOKEN", "") + IncludeStablesParam = env.GetEnv("INCLUDE_STABLES_PARAM", "false") _, err = url.Parse(custodialURLBase) if err != nil { From 343d30a2f27cabf2962f41e818396d351f775601 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 21 May 2025 15:42:06 +0300 Subject: [PATCH 39/50] rename the variables and read the stables param from the config --- remote/http/service.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index 612a93b..00c055a 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -403,20 +403,23 @@ func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolA PoolSwappableVouchers []dataserviceapi.TokenHoldings `json:"filtered"` } - ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to") - if err != nil { - return nil, err - } - u, err := url.Parse(ep) + basePath, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to") if err != nil { return nil, err } - query := u.Query() - query.Set("stable", "true") - u.RawQuery = query.Encode() + parsedURL, err := url.Parse(basePath) + if err != nil { + return nil, err + } - req, err := http.NewRequest("GET", u.String(), nil) + query := parsedURL.Query() + if config.IncludeStablesParam != "" { + query.Set("stables", config.IncludeStablesParam) + } + parsedURL.RawQuery = query.Encode() + + req, err := http.NewRequest("GET", parsedURL.String(), nil) if err != nil { return nil, err } From 62cc5eed890dc6f07dfdd17cf1148ad544afba79 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 21 May 2025 17:10:25 +0300 Subject: [PATCH 40/50] use the updated ussd-data-service --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c1f6922..bb98e4e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta - github.com/grassrootseconomics/ussd-data-service v1.4.4-beta + github.com/grassrootseconomics/ussd-data-service v1.4.7-beta github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 857291f..928c0bb 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/grassrootseconomics/ussd-data-service v1.4.0-beta h1:4fMd/3h2ZIhRg4Gd github.com/grassrootseconomics/ussd-data-service v1.4.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/grassrootseconomics/ussd-data-service v1.4.4-beta h1:turlyo0i3OLj29mWpWNoB/3Qao8qEngT/5d1jDWTZE4= github.com/grassrootseconomics/ussd-data-service v1.4.4-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= +github.com/grassrootseconomics/ussd-data-service v1.4.7-beta h1:yAe1YaOBsdxW2m20jnVU4F0kLmFr+mK/gHCWEdHmE90= +github.com/grassrootseconomics/ussd-data-service v1.4.7-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= From 6c3719e3b652b3831e134cc4d4d4eb1829036230 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Wed, 21 May 2025 17:12:46 +0300 Subject: [PATCH 41/50] Fix: use the correct TokenDetails in the GetPoolSwappableVouchers --- dev/api.go | 13 ++++++------- remote/account_service.go | 2 +- remote/http/service.go | 6 +++--- testutil/mocks/service_mock.go | 4 ++-- testutil/testservice/account_service.go | 4 ++-- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/dev/api.go b/dev/api.go index 00e14d8..13ffc4f 100644 --- a/dev/api.go +++ b/dev/api.go @@ -852,18 +852,17 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, return swapFromList, nil } -func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { - var swapToList []dataserviceapi.TokenHoldings +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { + var swapToList []dataserviceapi.TokenDetails _, ok := das.pools[poolAddress] if !ok { return nil, fmt.Errorf("Invalid pool address: %v", poolAddress) } for _, voucher := range das.vouchers { - swapToList = append(swapToList, dataserviceapi.TokenHoldings{ - ContractAddress: voucher.Address, - TokenSymbol: voucher.Symbol, - TokenDecimals: string(defaultDecimals), - Balance: fmt.Sprintf("%f", defaultVoucherBalance), + swapToList = append(swapToList, dataserviceapi.TokenDetails{ + TokenAddress: voucher.Address, + TokenSymbol: voucher.Symbol, + TokenDecimals: defaultDecimals, }) } return swapToList, nil diff --git a/remote/account_service.go b/remote/account_service.go index 4050295..bafa665 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -23,7 +23,7 @@ type AccountService interface { PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) - GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) + GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) diff --git a/remote/http/service.go b/remote/http/service.go index 00c055a..4d124de 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -389,7 +389,7 @@ func (as *HTTPAccountService) getPoolSwappableFromVouchers(ctx context.Context, return r.PoolSwappableVouchers, nil } -func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { +func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { svc := dev.NewDevAccountService(ctx, as.SS) if as.UseApi { return as.getPoolSwappableVouchers(ctx, poolAddress) @@ -398,9 +398,9 @@ func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, pool } } -func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { +func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { var r struct { - PoolSwappableVouchers []dataserviceapi.TokenHoldings `json:"filtered"` + PoolSwappableVouchers []dataserviceapi.TokenDetails `json:"filtered"` } basePath, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to") diff --git a/testutil/mocks/service_mock.go b/testutil/mocks/service_mock.go index 1c0ee97..4ea9cd8 100644 --- a/testutil/mocks/service_mock.go +++ b/testutil/mocks/service_mock.go @@ -86,9 +86,9 @@ func (m MockAccountService) GetPoolSwappableFromVouchers(ctx context.Context, po return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } -func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { +func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { args := m.Called(poolAddress) - return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) + return args.Get(0).([]dataserviceapi.TokenDetails), args.Error(1) } func (m MockAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index f9c69ef..a9e1d0d 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -89,8 +89,8 @@ func (m TestAccountService) GetPoolSwappableFromVouchers(ctx context.Context, po return []dataserviceapi.TokenHoldings{}, nil } -func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { - return []dataserviceapi.TokenHoldings{}, nil +func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { + return []dataserviceapi.TokenDetails{}, nil } func (m TestAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { From 24224e553de57f7414f05638163cb6988abd7a70 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 22 May 2025 15:31:08 +0300 Subject: [PATCH 42/50] use the correct PoolSwapURL when performing the actual swap --- remote/http/service.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/remote/http/service.go b/remote/http/service.go index 4d124de..2a7fce5 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -351,6 +351,7 @@ func (as *HTTPAccountService) GetPoolSwapQuote(ctx context.Context, amount, from if err != nil { return nil, err } + req, err := http.NewRequest("POST", config.PoolSwapQuoteURL, bytes.NewBuffer(payloadBytes)) if err != nil { return nil, err @@ -444,7 +445,8 @@ func (as *HTTPAccountService) PoolSwap(ctx context.Context, amount, from, fromTo if err != nil { return nil, err } - req, err := http.NewRequest("POST", config.PoolSwapQuoteURL, bytes.NewBuffer(payloadBytes)) + + req, err := http.NewRequest("POST", config.PoolSwapURL, bytes.NewBuffer(payloadBytes)) if err != nil { return nil, err } From bf830e92dea2310bb7fe9df4244fd53ab51cc0c5 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 5 Jun 2025 20:41:08 +0300 Subject: [PATCH 43/50] add the RetrievePoolDetails to the account_service --- remote/account_service.go | 1 + 1 file changed, 1 insertion(+) diff --git a/remote/account_service.go b/remote/account_service.go index bafa665..020a21a 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -22,6 +22,7 @@ type AccountService interface { SendPINResetSMS(ctx context.Context, admin, phone string) error PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) + RetrievePoolDetails(ctx context.Context, sym string) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) From b5ccaea57560984cdc0d1c1a0f9308a8703aabe8 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 6 Jun 2025 22:42:35 +0300 Subject: [PATCH 44/50] add the RetrievePoolDetails to the testutil and dev account service --- dev/api.go | 12 ++++++++++++ remote/account_service.go | 2 +- testutil/mocks/service_mock.go | 5 +++++ testutil/testservice/account_service.go | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dev/api.go b/dev/api.go index 13ffc4f..15bf94b 100644 --- a/dev/api.go +++ b/dev/api.go @@ -833,6 +833,18 @@ func (das *DevAccountService) FetchTopPools(ctx context.Context) ([]dataservicea return topPools, nil } +func (das *DevAccountService) RetrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) { + testPool := &dataserviceapi.PoolDetails{ + PoolName: "DevTest", + PoolSymbol: "DEVT", + PoolContractAdrress: "0x145F87d6198dEDD45C614FFD8b70E9a2fCCc5cc9", + LimiterAddress: "", + VoucherRegistry: "", + } + + return testPool, nil +} + func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { var swapFromList []dataserviceapi.TokenHoldings diff --git a/remote/account_service.go b/remote/account_service.go index 020a21a..ea1fffb 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -22,7 +22,7 @@ type AccountService interface { SendPINResetSMS(ctx context.Context, admin, phone string) error PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) - RetrievePoolDetails(ctx context.Context, sym string) + RetrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) diff --git a/testutil/mocks/service_mock.go b/testutil/mocks/service_mock.go index 4ea9cd8..e00377d 100644 --- a/testutil/mocks/service_mock.go +++ b/testutil/mocks/service_mock.go @@ -81,6 +81,11 @@ func (m MockAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi return args.Get(0).([]dataserviceapi.PoolDetails), args.Error(1) } +func (m MockAccountService) RetrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) { + args := m.Called() + return args.Get(0).(*dataserviceapi.PoolDetails), args.Error(1) +} + func (m MockAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { args := m.Called(poolAddress, publicKey) return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index a9e1d0d..5766184 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -85,6 +85,10 @@ func (m TestAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi return []dataserviceapi.PoolDetails{}, nil } +func (m TestAccountService) RetrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) { + return &dataserviceapi.PoolDetails{}, nil +} + func (m TestAccountService) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) { return []dataserviceapi.TokenHoldings{}, nil } From 54dfe037b403af7ac01e6a0c671c1dca855b61d9 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 23 Jun 2025 09:31:53 +0300 Subject: [PATCH 45/50] updated the ussd-data-service to tag v1.5.0-beta --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index bb98e4e..2e4c035 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta - github.com/grassrootseconomics/ussd-data-service v1.4.7-beta + github.com/grassrootseconomics/ussd-data-service v1.5.0-beta github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 928c0bb..6480970 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/grassrootseconomics/ussd-data-service v1.4.4-beta h1:turlyo0i3OLj29mW github.com/grassrootseconomics/ussd-data-service v1.4.4-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/grassrootseconomics/ussd-data-service v1.4.7-beta h1:yAe1YaOBsdxW2m20jnVU4F0kLmFr+mK/gHCWEdHmE90= github.com/grassrootseconomics/ussd-data-service v1.4.7-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= +github.com/grassrootseconomics/ussd-data-service v1.5.0-beta h1:BSSQL/yPEvTVku9ja/ENZyZdwZkEaiTzzOUfg72bTy4= +github.com/grassrootseconomics/ussd-data-service v1.5.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= From c1797e7a32b5bf08fc7d8bfe7c7d8ddad29b1533 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 23 Jun 2025 09:32:34 +0300 Subject: [PATCH 46/50] use the TokenHoldings instead of TokenDetails --- dev/api.go | 10 +++++----- remote/account_service.go | 2 +- remote/http/service.go | 6 +++--- testutil/mocks/service_mock.go | 4 ++-- testutil/testservice/account_service.go | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dev/api.go b/dev/api.go index 15bf94b..65a2b19 100644 --- a/dev/api.go +++ b/dev/api.go @@ -864,17 +864,17 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, return swapFromList, nil } -func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { - var swapToList []dataserviceapi.TokenDetails +func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { + var swapToList []dataserviceapi.TokenHoldings _, ok := das.pools[poolAddress] if !ok { return nil, fmt.Errorf("Invalid pool address: %v", poolAddress) } for _, voucher := range das.vouchers { - swapToList = append(swapToList, dataserviceapi.TokenDetails{ - TokenAddress: voucher.Address, + swapToList = append(swapToList, dataserviceapi.TokenHoldings{ + ContractAddress: voucher.Address, TokenSymbol: voucher.Symbol, - TokenDecimals: defaultDecimals, + TokenDecimals: strconv.Itoa(voucher.Decimals), }) } return swapToList, nil diff --git a/remote/account_service.go b/remote/account_service.go index ea1fffb..d9708ef 100644 --- a/remote/account_service.go +++ b/remote/account_service.go @@ -24,7 +24,7 @@ type AccountService interface { FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) RetrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) GetPoolSwappableFromVouchers(ctx context.Context, poolAddress, publicKey string) ([]dataserviceapi.TokenHoldings, error) - GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) + GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, error) GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) diff --git a/remote/http/service.go b/remote/http/service.go index 2a7fce5..af8f056 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -390,7 +390,7 @@ func (as *HTTPAccountService) getPoolSwappableFromVouchers(ctx context.Context, return r.PoolSwappableVouchers, nil } -func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { +func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { svc := dev.NewDevAccountService(ctx, as.SS) if as.UseApi { return as.getPoolSwappableVouchers(ctx, poolAddress) @@ -399,9 +399,9 @@ func (as *HTTPAccountService) GetPoolSwappableVouchers(ctx context.Context, pool } } -func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { +func (as HTTPAccountService) getPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { var r struct { - PoolSwappableVouchers []dataserviceapi.TokenDetails `json:"filtered"` + PoolSwappableVouchers []dataserviceapi.TokenHoldings `json:"filtered"` } basePath, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "to") diff --git a/testutil/mocks/service_mock.go b/testutil/mocks/service_mock.go index e00377d..93d0358 100644 --- a/testutil/mocks/service_mock.go +++ b/testutil/mocks/service_mock.go @@ -91,9 +91,9 @@ func (m MockAccountService) GetPoolSwappableFromVouchers(ctx context.Context, po return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } -func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { +func (m MockAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { args := m.Called(poolAddress) - return args.Get(0).([]dataserviceapi.TokenDetails), args.Error(1) + return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } func (m MockAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index 5766184..3177c98 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -93,8 +93,8 @@ func (m TestAccountService) GetPoolSwappableFromVouchers(ctx context.Context, po return []dataserviceapi.TokenHoldings{}, nil } -func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenDetails, error) { - return []dataserviceapi.TokenDetails{}, nil +func (m TestAccountService) GetPoolSwappableVouchers(ctx context.Context, poolAddress string) ([]dataserviceapi.TokenHoldings, error) { + return []dataserviceapi.TokenHoldings{}, nil } func (m TestAccountService) GetPoolSwapQuote(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapQuoteResult, error) { From d945964b0b4625f8d709553b568af6751a89f480 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 23 Jun 2025 10:00:26 +0300 Subject: [PATCH 47/50] use the TokenAddress instead of ContractAddress --- dev/api.go | 6 +++--- go.mod | 2 +- go.sum | 2 ++ testutil/testservice/account_service.go | 8 ++++---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/dev/api.go b/dev/api.go index 65a2b19..26e1e4c 100644 --- a/dev/api.go +++ b/dev/api.go @@ -587,7 +587,7 @@ func (das *DevAccountService) FetchVouchers(ctx context.Context, publicKey strin //TODO: Iterate over the account acc.Balances object for _, voucher := range das.vouchers { holdings = append(holdings, dataserviceapi.TokenHoldings{ - ContractAddress: voucher.Address, + TokenAddress: voucher.Address, TokenSymbol: voucher.Symbol, TokenDecimals: strconv.Itoa(voucher.Decimals), Balance: strconv.Itoa(int(defaultVoucherBalance)), @@ -854,7 +854,7 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context, } for _, v := range p.Vouchers { swapFromList = append(swapFromList, dataserviceapi.TokenHoldings{ - ContractAddress: v.Address, + TokenAddress: v.Address, TokenSymbol: v.Symbol, TokenDecimals: string(defaultDecimals), Balance: fmt.Sprintf("%f", defaultVoucherBalance), @@ -872,7 +872,7 @@ func (das *DevAccountService) GetPoolSwappableVouchers(ctx context.Context, pool } for _, voucher := range das.vouchers { swapToList = append(swapToList, dataserviceapi.TokenHoldings{ - ContractAddress: voucher.Address, + TokenAddress: voucher.Address, TokenSymbol: voucher.Symbol, TokenDecimals: strconv.Itoa(voucher.Decimals), }) diff --git a/go.mod b/go.mod index 2e4c035..8acb98e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 github.com/gofrs/uuid v4.4.0+incompatible github.com/grassrootseconomics/eth-custodial v1.3.0-beta - github.com/grassrootseconomics/ussd-data-service v1.5.0-beta + github.com/grassrootseconomics/ussd-data-service v1.6.0-beta github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 6480970..470c903 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/grassrootseconomics/ussd-data-service v1.4.7-beta h1:yAe1YaOBsdxW2m20 github.com/grassrootseconomics/ussd-data-service v1.4.7-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/grassrootseconomics/ussd-data-service v1.5.0-beta h1:BSSQL/yPEvTVku9ja/ENZyZdwZkEaiTzzOUfg72bTy4= github.com/grassrootseconomics/ussd-data-service v1.5.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= +github.com/grassrootseconomics/ussd-data-service v1.6.0-beta h1:pY6zns6ifXyClRxP+JJaWrged3oRE7tTS2xaftF9clA= +github.com/grassrootseconomics/ussd-data-service v1.6.0-beta/go.mod h1:9sGnorpKaK76FmOGXoh/xv7x5siSFNYdXxQo9BKW4DI= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= diff --git a/testutil/testservice/account_service.go b/testutil/testservice/account_service.go index 3177c98..935df73 100644 --- a/testutil/testservice/account_service.go +++ b/testutil/testservice/account_service.go @@ -35,10 +35,10 @@ func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { return []dataserviceapi.TokenHoldings{ dataserviceapi.TokenHoldings{ - ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", - TokenSymbol: "SRF", - TokenDecimals: "6", - Balance: "2745987", + TokenAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", + TokenSymbol: "SRF", + TokenDecimals: "6", + Balance: "2745987", }, }, nil } From 7b42d509e6d428525bd8b3f7a3d63e9bc0c0fbb9 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 23 Jun 2025 10:50:57 +0300 Subject: [PATCH 48/50] log the request and response body --- remote/http/service.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index af8f056..25b2de4 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -653,6 +653,7 @@ func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKRespons req.Header.Set("Authorization", "Bearer "+config.BearerToken) req.Header.Set("Content-Type", "application/json") + // Log request logRequestDetails(req) resp, err := http.DefaultClient.Do(req) @@ -663,22 +664,26 @@ func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKRespons } defer resp.Body.Close() - log.Printf("Received response for %s: Status Code: %d | Content-Type: %s", req.URL, resp.StatusCode, resp.Header.Get("Content-Type")) + // Read and log response body body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } + + log.Printf("Received response for %s: Status Code: %d | Content-Type: %s | Body: %s", + req.URL, resp.StatusCode, resp.Header.Get("Content-Type"), string(body)) + if resp.StatusCode >= http.StatusBadRequest { - err := json.Unmarshal([]byte(body), &errResponse) - if err != nil { + if err := json.Unmarshal(body, &errResponse); err != nil { return nil, err } return nil, errors.New(errResponse.Description) } - err = json.Unmarshal([]byte(body), &okResponse) - if err != nil { + + if err := json.Unmarshal(body, &okResponse); err != nil { return nil, err } + if len(okResponse.Result) == 0 { return nil, errors.New("Empty api result") } @@ -695,16 +700,14 @@ func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKRespons func logRequestDetails(req *http.Request) { var bodyBytes []byte contentType := req.Header.Get("Content-Type") + if req.Body != nil { - bodyBytes, err := io.ReadAll(req.Body) - if err != nil { - log.Printf("Error reading request body: %s", err) - return - } - req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + bodyBytes, _ = io.ReadAll(req.Body) + req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // Restore body } else { bodyBytes = []byte("-") } - log.Printf("URL: %s | Content-Type: %s | Method: %s| Request Body: %s", req.URL, contentType, req.Method, string(bodyBytes)) + log.Printf("Outgoing Request -> URL: %s | Method: %s | Content-Type: %s | Body: %s", + req.URL.String(), req.Method, contentType, string(bodyBytes)) } From 5aa032400c12c37079477083abfa37f9fdacc980 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 24 Jun 2025 10:48:30 +0300 Subject: [PATCH 49/50] update the alias endpoints --- config/config.go | 13 ++++++------- remote/http/service.go | 29 +++++++++-------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/config/config.go b/config/config.go index f9a2e37..6f81fa7 100644 --- a/config/config.go +++ b/config/config.go @@ -15,7 +15,6 @@ const ( voucherHoldingsPathPrefix = "/api/v1/holdings" voucherTransfersPathPrefix = "/api/v1/transfers/last10" voucherDataPathPrefix = "/api/v1/token" - aliasPrefix = "api/v1/alias" SendSMSPrefix = "api/v1/external/upsell" poolDepositPrefix = "/api/v2/pool/deposit" poolSwapQoutePrefix = "/api/v2/pool/quote" @@ -23,7 +22,8 @@ const ( topPoolsPrefix = "/api/v1/pool/top" retrievePoolDetailsPrefix = "/api/v1/pool/reverse" poolSwappableVouchersPrefix = "/api/v1/pool" - AliasEnsPrefix = "/api/v1/bypass" + AliasRegistrationPrefix = "/api/v1/internal/register" + AliasResolverPrefix = "/api/v1/resolve" ExternalSMSPrefix = "/api/v1/external" ) @@ -45,7 +45,6 @@ var ( VoucherHoldingsURL string VoucherTransfersURL string VoucherDataURL string - CheckAliasURL string PoolDepositURL string PoolSwapQuoteURL string PoolSwapURL string @@ -53,7 +52,8 @@ var ( RetrievePoolDetailsURL string PoolSwappableVouchersURL string SendSMSURL string - AliasEnsURL string + AliasRegistrationURL string + AliasResolverURL string ExternalSMSURL string ) @@ -92,7 +92,6 @@ func LoadConfig() error { VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) VoucherDataURL, _ = url.JoinPath(dataURLBase, voucherDataPathPrefix) - CheckAliasURL, _ = url.JoinPath(dataURLBase, aliasPrefix) SendSMSURL, _ = url.JoinPath(dataURLBase, SendSMSPrefix) PoolDepositURL, _ = url.JoinPath(custodialURLBase, poolDepositPrefix) PoolSwapQuoteURL, _ = url.JoinPath(custodialURLBase, poolSwapQoutePrefix) @@ -100,8 +99,8 @@ func LoadConfig() error { TopPoolsURL, _ = url.JoinPath(dataURLBase, topPoolsPrefix) RetrievePoolDetailsURL, _ = url.JoinPath(dataURLBase, retrievePoolDetailsPrefix) PoolSwappableVouchersURL, _ = url.JoinPath(dataURLBase, poolSwappableVouchersPrefix) - - AliasEnsURL, _ = url.JoinPath(aliasEnsURLBase, AliasEnsPrefix) + AliasRegistrationURL, _ = url.JoinPath(aliasEnsURLBase, AliasRegistrationPrefix) + AliasResolverURL, _ = url.JoinPath(aliasEnsURLBase, AliasResolverPrefix) ExternalSMSURL, _ = url.JoinPath(externalSMSBase, ExternalSMSPrefix) return nil diff --git a/remote/http/service.go b/remote/http/service.go index 25b2de4..d1b9773 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -234,33 +234,24 @@ func (as *HTTPAccountService) CheckAliasAddress(ctx context.Context, alias strin } func resolveAliasAddress(ctx context.Context, alias string) (*models.AliasAddress, error) { - var ( - aliasEnsResult models.AliasEnsAddressResult - ) + var aliasEnsResult models.AliasEnsAddressResult - ep, err := url.JoinPath(config.CheckAliasURL, "/resolve") + fullURL, err := url.JoinPath(config.AliasResolverURL, alias) if err != nil { return nil, err } - u, err := url.Parse(ep) + req, err := http.NewRequest("GET", fullURL, nil) if err != nil { return nil, err } - query := u.Query() - query.Set("name", alias) - u.RawQuery = query.Encode() - - req, err := http.NewRequest("GET", u.String(), nil) - if err != nil { - return nil, err - } _, err = doRequest(ctx, req, &aliasEnsResult) if err != nil { return nil, err } - return &models.AliasAddress{Address: aliasEnsResult.Address}, err + + return &models.AliasAddress{Address: aliasEnsResult.Address}, nil } func (as *HTTPAccountService) FetchTopPools(ctx context.Context) ([]dataserviceapi.PoolDetails, error) { @@ -536,11 +527,9 @@ func (as *HTTPAccountService) RequestAlias(ctx context.Context, publicKey string func requestEnsAlias(ctx context.Context, publicKey string, hint string) (*models.AliasEnsResult, error) { var r models.AliasEnsResult - ep, err := url.JoinPath(config.CheckAliasURL, "/register") - if err != nil { - return nil, err - } - logg.InfoCtxf(ctx, "requesting alias", "endpoint", ep, "hint", hint) + endpoint := config.AliasRegistrationURL + + logg.InfoCtxf(ctx, "requesting alias", "endpoint", endpoint, "hint", hint) //Payload with the address and hint to derive an ENS name payload := map[string]string{ "address": publicKey, @@ -550,7 +539,7 @@ func requestEnsAlias(ctx context.Context, publicKey string, hint string) (*model if err != nil { return nil, err } - req, err := http.NewRequest("POST", ep, bytes.NewBuffer(payloadBytes)) + req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payloadBytes)) if err != nil { return nil, err } From 339ba854c997a8e9386f263f45e03dc7dee4e857 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Tue, 24 Jun 2025 12:07:44 +0300 Subject: [PATCH 50/50] fix: correctly unmarshal nested pool details response in retrievePoolDeta --- remote/http/service.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/remote/http/service.go b/remote/http/service.go index d1b9773..1c41ab7 100644 --- a/remote/http/service.go +++ b/remote/http/service.go @@ -286,7 +286,9 @@ func (as *HTTPAccountService) RetrievePoolDetails(ctx context.Context, sym strin } func retrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolDetails, error) { - var r dataserviceapi.PoolDetails + var r struct { + PoolDetails dataserviceapi.PoolDetails `json:"poolDetails"` + } ep, err := url.JoinPath(config.RetrievePoolDetailsURL, sym) if err != nil { @@ -297,7 +299,11 @@ func retrievePoolDetails(ctx context.Context, sym string) (*dataserviceapi.PoolD return nil, err } _, err = doRequest(ctx, req, &r) - return &r, nil + if err != nil { + return nil, err + } + + return &r.PoolDetails, nil } func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poolAddress, tokenAddress string) (*models.PoolDepositResult, error) { @@ -528,7 +534,7 @@ func requestEnsAlias(ctx context.Context, publicKey string, hint string) (*model var r models.AliasEnsResult endpoint := config.AliasRegistrationURL - + logg.InfoCtxf(ctx, "requesting alias", "endpoint", endpoint, "hint", hint) //Payload with the address and hint to derive an ENS name payload := map[string]string{