Compare commits

..

No commits in common. "master" and "handle-error-codes" have entirely different histories.

10 changed files with 113 additions and 326 deletions

View File

@ -7,66 +7,56 @@ 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"
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"
AliasRegistrationPrefix = "/api/v1/internal/register"
AliasResolverPrefix = "/api/v1/resolve"
ExternalSMSPrefix = "/api/v1/external"
AliasUpdatePrefix = "/api/v1/internal/update"
CreditSendPrefix = "/api/v1/credit-send"
CreditSendReverseQuotePrefix = "/api/v1/pool/reverse-quote"
MpesaOnrampPath = "/api/v1/trigger-onramp"
MpesaOnrampRatesPath = "/api/v1/rates"
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"
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"
AliasRegistrationPrefix = "/api/v1/internal/register"
AliasResolverPrefix = "/api/v1/resolve"
ExternalSMSPrefix = "/api/v1/external"
AliasUpdatePrefix = "/api/v1/internal/update"
)
var (
custodialURLBase string
dataURLBase string
BearerToken string
aliasEnsURLBase string
externalSMSBase string
IncludeStablesParam string
MpesaOnrampBearerToken string
mpesaOnrampBase string
custodialURLBase string
dataURLBase string
BearerToken string
aliasEnsURLBase string
externalSMSBase string
IncludeStablesParam string
)
var (
CreateAccountURL string
TrackStatusURL string
BalanceURL string
TrackURL string
TokenTransferURL string
VoucherHoldingsURL string
VoucherTransfersURL string
VoucherDataURL string
PoolDepositURL string
PoolSwapQuoteURL string
PoolSwapURL string
TopPoolsURL string
RetrievePoolDetailsURL string
PoolSwappableVouchersURL string
SendSMSURL string
AliasRegistrationURL string
AliasResolverURL string
ExternalSMSURL string
AliasUpdateURL string
CreditSendURL string
CreditSendReverseQuoteURL string
MpesaOnrampURL string
MpresaOnrampRatesURL string
CreateAccountURL string
TrackStatusURL string
BalanceURL string
TrackURL string
TokenTransferURL string
VoucherHoldingsURL string
VoucherTransfersURL string
VoucherDataURL string
PoolDepositURL string
PoolSwapQuoteURL string
PoolSwapURL string
TopPoolsURL string
RetrievePoolDetailsURL string
PoolSwappableVouchersURL string
SendSMSURL string
AliasRegistrationURL string
AliasResolverURL string
ExternalSMSURL string
AliasUpdateURL string
)
func setBase() error {
@ -78,8 +68,6 @@ func setBase() error {
externalSMSBase = env.GetEnv("EXTERNAL_SMS_BASE", "http://localhost:5035")
BearerToken = env.GetEnv("BEARER_TOKEN", "")
IncludeStablesParam = env.GetEnv("INCLUDE_STABLES_PARAM", "false")
MpesaOnrampBearerToken = env.GetEnv("MPESA_BEARER_TOKEN", "")
mpesaOnrampBase = env.GetEnv("MPESA_ONRAMP_BASE", "https://pretium.v1.grassecon.net")
_, err = url.Parse(custodialURLBase)
if err != nil {
@ -117,10 +105,6 @@ func LoadConfig() error {
AliasResolverURL, _ = url.JoinPath(aliasEnsURLBase, AliasResolverPrefix)
ExternalSMSURL, _ = url.JoinPath(externalSMSBase, ExternalSMSPrefix)
AliasUpdateURL, _ = url.JoinPath(aliasEnsURLBase, AliasUpdatePrefix)
CreditSendURL, _ = url.JoinPath(dataURLBase, CreditSendPrefix)
CreditSendReverseQuoteURL, _ = url.JoinPath(dataURLBase, CreditSendReverseQuotePrefix)
MpesaOnrampURL, _ = url.JoinPath(mpesaOnrampBase, MpesaOnrampPath)
MpresaOnrampRatesURL, _ = url.JoinPath(mpesaOnrampBase, MpesaOnrampRatesPath)
return nil
}

View File

@ -587,10 +587,10 @@ 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{
TokenAddress: voucher.Address,
TokenSymbol: voucher.Symbol,
TokenDecimals: strconv.Itoa(voucher.Decimals),
Balance: strconv.Itoa(int(defaultVoucherBalance)),
TokenAddress: voucher.Address,
TokenSymbol: voucher.Symbol,
TokenDecimals: strconv.Itoa(voucher.Decimals),
Balance: strconv.Itoa(int(defaultVoucherBalance)),
})
}
@ -861,10 +861,10 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context,
}
for _, v := range p.Vouchers {
swapFromList = append(swapFromList, dataserviceapi.TokenHoldings{
TokenAddress: v.Address,
TokenSymbol: v.Symbol,
TokenDecimals: string(defaultDecimals),
Balance: fmt.Sprintf("%f", defaultVoucherBalance),
TokenAddress: v.Address,
TokenSymbol: v.Symbol,
TokenDecimals: string(defaultDecimals),
Balance: fmt.Sprintf("%f", defaultVoucherBalance),
})
}
@ -907,32 +907,3 @@ func (das *DevAccountService) CheckTokenInPool(ctx context.Context, poolAddress,
CanSwapFrom: true,
}, nil
}
func (das *DevAccountService) GetCreditSendMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.CreditSendLimitsResult, error) {
return &models.CreditSendLimitsResult{
MaxRAT: "45599996",
MaxSAT: "3507692",
}, nil
}
func (das *DevAccountService) GetCreditSendReverseQuote(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount string) (*models.CreditSendReverseQouteResult, error) {
return &models.CreditSendReverseQouteResult{
InputAmount: "3076923",
OutputAmount: "40000000",
}, nil
}
func (das *DevAccountService) MpesaTriggerOnramp(ctx context.Context, address, phoneNumber, asset string, amount int) (*models.MpesaOnrampResponse, error) {
return &models.MpesaOnrampResponse{
Message: "Success, kindly accept prompt sent.",
Status: "PENDING",
TransactionCode: "ae6fb33b-4653-4f38-a3b6-85dfea7a1e99",
}, nil
}
func (das *DevAccountService) GetMpesaOnrampRates(ctx context.Context) (*models.MpesaOnrampRatesResponse, error) {
return &models.MpesaOnrampRatesResponse{
Buy: 128.15,
Sell: 130.06,
}, nil
}

32
go.mod
View File

@ -1,38 +1,36 @@
module git.grassecon.net/grassrootseconomics/sarafu-api
go 1.24.0
toolchain go1.24.6
go 1.23.4
require (
git.defalsify.org/vise.git v0.2.3-0.20250204132233-2bffe532f21e
git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2
git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d
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.12.0-rc
github.com/grassrootseconomics/ussd-data-service v1.10.1-beta
github.com/stretchr/testify v1.11.1
github.com/grassrootseconomics/eth-custodial v1.3.0-beta
github.com/grassrootseconomics/ussd-data-service v1.6.0-beta
github.com/stretchr/testify v1.9.0
)
require (
github.com/barbashov/iso639-3 v1.0.0 // indirect
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.6 // indirect
github.com/jackc/pgx/v5 v5.7.1 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect
github.com/pashagolub/pgxmock/v4 v4.7.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/stretchr/objx v0.5.3 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.21.0 // indirect
gopkg.in/leonelquinteros/gotext.v1 v1.3.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

67
go.sum
View File

@ -1,30 +1,41 @@
git.defalsify.org/vise.git v0.2.3-0.20250204132233-2bffe532f21e h1:gtB9OdX6x5gQRM3W824dEurXuuf/YPInqgtv2KAp5Zo=
git.defalsify.org/vise.git v0.2.3-0.20250204132233-2bffe532f21e/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1 h1:eppylYmQ9izyar0HIhb0Qbnat33EJYaH+5bFpp2PSkg=
git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2 h1:YFztSsexCUgFo6M0tbngRwYdgJd3LQV3RO/Jw09u3+k=
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w=
github.com/barbashov/iso639-3 v1.0.0 h1:qCp1hUzZT8C8yHcdDo4sZQg2jHEaX6LF5H/dF9ba0qs=
github.com/barbashov/iso639-3 v1.0.0/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U=
git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9 h1:sPcqXQcywxA8W3W+9qQncLPmsrgqTIlec7vmD4/7vyA=
git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d h1:5mzLas+jxTUtusOKx4XvU+n2QvrV/mH17MnJRy46siQ=
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 h1:ON77G5K0JNuwPb5JT/hRfF6G6+xstlBQgEIEzWydnhg=
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2/go.mod h1:pjKp9L/ZsWW3kMB0UoIl1yv9TBIuU33mn9Aghxp7vGk=
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c h1:H9Nm+I7Cg/YVPpEV1RzU3Wq2pjamPc/UtHDgItcb7lE=
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/grassrootseconomics/eth-custodial v1.12.0-rc h1:INkXMfNUISkQ1bgnw3LwfFJn/eCdBawFU8Hx+S7mM/c=
github.com/grassrootseconomics/eth-custodial v1.12.0-rc/go.mod h1:s/vacSWFiVO7FDv76EID8sQvdT1vq+3GcWZUgU6N618=
github.com/grassrootseconomics/ussd-data-service v1.10.1-beta h1:ZrRn7gv4MVSg67hmSdiii/Y86PUIvhxtqc2luAjlA7o=
github.com/grassrootseconomics/ussd-data-service v1.10.1-beta/go.mod h1:Uigrnnwj0vaTz2az3VwHmAG7xpJgQWYTcLudLh6Zc1I=
github.com/grassrootseconomics/eth-custodial v1.3.0-beta h1:twrMBhl89GqDUL9PlkzQxMP/6OST1BByrNDj+rqXDmU=
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/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/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=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
@ -35,8 +46,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a h1:0Q3H0YXzMHiciXtRcM+j0jiCe8WKPQHoRgQiRTnfcLY=
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a/go.mod h1:CdTTBOYzS5E4mWS1N8NWP6AHI19MP0A2B18n3hLzRMk=
github.com/pashagolub/pgxmock/v4 v4.7.0 h1:de2ORuFYyjwOQR7NBm57+321RnZxpYiuUjsmqRiqgh8=
github.com/pashagolub/pgxmock/v4 v4.7.0/go.mod h1:9L57pC193h2aKRHVyiiE817avasIPZnPwPlw3JczWvM=
github.com/pashagolub/pgxmock/v4 v4.3.0 h1:DqT7fk0OCK6H0GvqtcMsLpv8cIwWqdxWgfZNLeHCb/s=
github.com/pashagolub/pgxmock/v4 v4.3.0/go.mod h1:9VoVHXwS3XR/yPtKGzwQvwZX1kzGB9sM8SviDcHDa3A=
github.com/peteole/testdata-loader v0.3.0 h1:8jckE9KcyNHgyv/VPoaljvKZE0Rqr8+dPVYH6rfNr9I=
github.com/peteole/testdata-loader v0.3.0/go.mod h1:Mt0ZbRtb56u8SLJpNP+BnQbENljMorYBpqlvt3cS83U=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -45,20 +56,20 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@ -1,12 +0,0 @@
package models
type MpesaOnrampResponse struct {
Message string `json:"message"`
Status string `json:"status"`
TransactionCode string `json:"transactionCode"`
}
type MpesaOnrampRatesResponse struct {
Buy float64 `json:"buy"`
Sell float64 `json:"sell"`
}

View File

@ -20,13 +20,3 @@ type MaxLimitResult struct {
type TokenInPoolResult struct {
CanSwapFrom bool `json:"canSwapFrom"`
}
type CreditSendLimitsResult struct {
MaxRAT string `json:"maxRAT"`
MaxSAT string `json:"maxSAT"`
}
type CreditSendReverseQouteResult struct {
InputAmount string `json:"inputAmount"`
OutputAmount string `json:"outputAmount"`
}

View File

@ -30,8 +30,4 @@ type AccountService interface {
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)
GetCreditSendMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.CreditSendLimitsResult, error)
GetCreditSendReverseQuote(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount string) (*models.CreditSendReverseQouteResult, error)
MpesaTriggerOnramp(ctx context.Context, address, phoneNumber, asset string, amount int) (*models.MpesaOnrampResponse, error)
GetMpesaOnrampRates(ctx context.Context) (*models.MpesaOnrampRatesResponse, error)
}

View File

@ -10,6 +10,7 @@ import (
"log"
"net/http"
"net/url"
"regexp"
"strings"
"git.defalsify.org/vise.git/logging"
@ -22,6 +23,7 @@ import (
)
var (
aliasRegex = regexp.MustCompile("^\\+?[a-zA-Z0-9\\-_]+$")
logg = logging.NewVanilla().WithDomain("sarafu-api.devapi")
)
@ -30,10 +32,6 @@ type APIError struct {
Description string
}
type ctxKey string
const ctxKeyAuthToken ctxKey = "authToken"
func (e *APIError) Error() string {
if e.Code != "" {
return fmt.Sprintf("[%s] %s", e.Code, e.Description)
@ -361,7 +359,7 @@ func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poo
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", config.PoolDepositURL, bytes.NewBuffer(payloadBytes))
req, err := http.NewRequest("POST", config.TokenTransferURL, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
@ -519,10 +517,10 @@ func (as *HTTPAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, pool
}
}
func (as *HTTPAccountService) getSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error) {
func (as *HTTPAccountService) getSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokeAddress, publicKey string) (*models.MaxLimitResult, error) {
var r models.MaxLimitResult
ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "limit", fromTokenAddress, toTokenAddress, publicKey)
ep, err := url.JoinPath(config.PoolSwappableVouchersURL, poolAddress, "limit", fromTokenAddress, toTokeAddress, publicKey)
if err != nil {
return nil, err
}
@ -744,117 +742,12 @@ func (as *HTTPAccountService) SendPINResetSMS(ctx context.Context, admin, phone
return nil
}
// GetCreditSendMaxLimit calls the API to check credit limits and return the maxRAT and maxSAT
func (as *HTTPAccountService) GetCreditSendMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.CreditSendLimitsResult, error) {
var r models.CreditSendLimitsResult
ep, err := url.JoinPath(config.CreditSendURL, poolAddress, fromTokenAddress, toTokenAddress, 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)
if err != nil {
return nil, err
}
return &r, nil
}
// GetCreditSendReverseQuote calls the API to getthe reverse quote for sending RAT amount
func (as *HTTPAccountService) GetCreditSendReverseQuote(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount string) (*models.CreditSendReverseQouteResult, error) {
var r models.CreditSendReverseQouteResult
ep, err := url.JoinPath(config.CreditSendReverseQuoteURL, poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount)
if err != nil {
return nil, err
}
req, err := http.NewRequest("GET", ep, nil)
if err != nil {
return nil, err
}
_, err = doRequest(ctx, req, &r)
if err != nil {
return nil, err
}
return &r, nil
}
// MpesaTriggerOnramp calls the API to perform an STK Push.
// Parameters:
// - address: The user's public key.
// - phoneNumber: The user's phone number
// - asset: the intented USD voucher "USDT | USDC | cUSD"
// - amount: The amount in Kenyan shillings
func (as *HTTPAccountService) MpesaTriggerOnramp(ctx context.Context, address, phoneNumber, asset string, amount int) (*models.MpesaOnrampResponse, error) {
var r models.MpesaOnrampResponse
ctx = context.WithValue(ctx, ctxKeyAuthToken, config.MpesaOnrampBearerToken)
// Prepare payload
payload := struct {
Address string `json:"address"`
PhoneNumber string `json:"phoneNumber"`
Asset string `json:"asset"`
Amount int `json:"amount"`
}{
Address: strings.TrimSpace(address),
PhoneNumber: strings.TrimSpace(phoneNumber),
Asset: strings.TrimSpace(asset),
Amount: amount,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
return nil, fmt.Errorf("failed to marshal mpesa onramp payload: %w", err)
}
req, err := http.NewRequest("POST", config.MpesaOnrampURL, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
if _, err := doRequest(ctx, req, &r); err != nil {
return nil, err
}
return &r, nil
}
// GetMpesaOnrampRates calls the API to fetch the buying and selling rates for KSH.
func (as *HTTPAccountService) GetMpesaOnrampRates(ctx context.Context) (*models.MpesaOnrampRatesResponse, error) {
var r models.MpesaOnrampRatesResponse
ctx = context.WithValue(ctx, ctxKeyAuthToken, config.MpesaOnrampBearerToken)
req, err := http.NewRequest("GET", config.MpresaOnrampRatesURL, nil)
if err != nil {
return nil, err
}
if _, err := doRequest(ctx, req, &r); err != nil {
return nil, err
}
return &r, nil
}
// TODO: remove eth-custodial api dependency
func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) {
var okResponse api.OKResponse
var errResponse api.ErrResponse
// Check if a custom Authorization token was provided
if token, ok := ctx.Value(ctxKeyAuthToken).(string); ok && token != "" {
req.Header.Set("Authorization", "Bearer "+token)
} else {
req.Header.Set("Authorization", "Bearer "+config.BearerToken)
}
req.Header.Set("Authorization", "Bearer "+config.BearerToken)
req.Header.Set("Content-Type", "application/json")
// Log request

View File

@ -120,23 +120,3 @@ func (m MockAccountService) CheckTokenInPool(ctx context.Context, poolAddress, t
args := m.Called(poolAddress, tokenAddress)
return args.Get(0).(*models.TokenInPoolResult), args.Error(1)
}
func (m MockAccountService) GetCreditSendMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.CreditSendLimitsResult, error) {
args := m.Called(poolAddress, fromTokenAddress, toTokenAddress, publicKey)
return args.Get(0).(*models.CreditSendLimitsResult), args.Error(1)
}
func (m MockAccountService) GetCreditSendReverseQuote(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount string) (*models.CreditSendReverseQouteResult, error) {
args := m.Called(poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount)
return args.Get(0).(*models.CreditSendReverseQouteResult), args.Error(1)
}
func (m MockAccountService) MpesaTriggerOnramp(ctx context.Context, address, phoneNumber, asset string, amount int) (*models.MpesaOnrampResponse, error) {
args := m.Called(address, phoneNumber, asset, amount)
return args.Get(0).(*models.MpesaOnrampResponse), args.Error(1)
}
func (m MockAccountService) GetMpesaOnrampRates(ctx context.Context) (*models.MpesaOnrampRatesResponse, error) {
args := m.Called()
return args.Get(0).(*models.MpesaOnrampRatesResponse), args.Error(1)
}

View File

@ -8,8 +8,6 @@ import (
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
)
// This is used in the menu traversal tests
type TestAccountService struct {
}
@ -36,18 +34,12 @@ 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{
TokenAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee",
TokenSymbol: "SRF",
TokenDecimals: "6",
Balance: "2745987",
},
{
TokenAddress: "0x3f195a3F68BF4c6D49748eFa033a00C6634fF311",
TokenSymbol: "USD",
TokenDecimals: "6",
Balance: "4269100",
},
}, nil
}
@ -124,19 +116,3 @@ func (m TestAccountService) GetSwapFromTokenMaxLimit(ctx context.Context, poolAd
func (m TestAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) {
return &models.TokenInPoolResult{}, nil
}
func (m TestAccountService) GetCreditSendMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.CreditSendLimitsResult, error) {
return &models.CreditSendLimitsResult{}, nil
}
func (m TestAccountService) GetCreditSendReverseQuote(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, toTokenAMount string) (*models.CreditSendReverseQouteResult, error) {
return &models.CreditSendReverseQouteResult{}, nil
}
func (m TestAccountService) MpesaTriggerOnramp(ctx context.Context, address, phoneNumber, asset string, amount int) (*models.MpesaOnrampResponse, error) {
return &models.MpesaOnrampResponse{}, nil
}
func (m TestAccountService) GetMpesaOnrampRates(ctx context.Context) (*models.MpesaOnrampRatesResponse, error) {
return &models.MpesaOnrampRatesResponse{}, nil
}