Compare commits
No commits in common. "master" and "sanitize-symbols" have entirely different histories.
master
...
sanitize-s
104
config/config.go
104
config/config.go
@ -7,66 +7,56 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
createAccountPath = "/api/v2/account/create"
|
createAccountPath = "/api/v2/account/create"
|
||||||
trackStatusPath = "/api/track"
|
trackStatusPath = "/api/track"
|
||||||
balancePathPrefix = "/api/account"
|
balancePathPrefix = "/api/account"
|
||||||
trackPath = "/api/v2/account/status"
|
trackPath = "/api/v2/account/status"
|
||||||
tokenTransferPrefix = "/api/v2/token/transfer"
|
tokenTransferPrefix = "/api/v2/token/transfer"
|
||||||
voucherHoldingsPathPrefix = "/api/v1/holdings"
|
voucherHoldingsPathPrefix = "/api/v1/holdings"
|
||||||
voucherTransfersPathPrefix = "/api/v1/transfers/last10"
|
voucherTransfersPathPrefix = "/api/v1/transfers/last10"
|
||||||
voucherDataPathPrefix = "/api/v1/token"
|
voucherDataPathPrefix = "/api/v1/token"
|
||||||
SendSMSPrefix = "api/v1/external/upsell"
|
SendSMSPrefix = "api/v1/external/upsell"
|
||||||
poolDepositPrefix = "/api/v2/pool/deposit"
|
poolDepositPrefix = "/api/v2/pool/deposit"
|
||||||
poolSwapQoutePrefix = "/api/v2/pool/quote"
|
poolSwapQoutePrefix = "/api/v2/pool/quote"
|
||||||
poolSwapPrefix = "/api/v2/pool/swap"
|
poolSwapPrefix = "/api/v2/pool/swap"
|
||||||
topPoolsPrefix = "/api/v1/pool/top"
|
topPoolsPrefix = "/api/v1/pool/top"
|
||||||
retrievePoolDetailsPrefix = "/api/v1/pool/reverse"
|
retrievePoolDetailsPrefix = "/api/v1/pool/reverse"
|
||||||
poolSwappableVouchersPrefix = "/api/v1/pool"
|
poolSwappableVouchersPrefix = "/api/v1/pool"
|
||||||
AliasRegistrationPrefix = "/api/v1/internal/register"
|
AliasRegistrationPrefix = "/api/v1/internal/register"
|
||||||
AliasResolverPrefix = "/api/v1/resolve"
|
AliasResolverPrefix = "/api/v1/resolve"
|
||||||
ExternalSMSPrefix = "/api/v1/external"
|
ExternalSMSPrefix = "/api/v1/external"
|
||||||
AliasUpdatePrefix = "/api/v1/internal/update"
|
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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
custodialURLBase string
|
custodialURLBase string
|
||||||
dataURLBase string
|
dataURLBase string
|
||||||
BearerToken string
|
BearerToken string
|
||||||
aliasEnsURLBase string
|
aliasEnsURLBase string
|
||||||
externalSMSBase string
|
externalSMSBase string
|
||||||
IncludeStablesParam string
|
IncludeStablesParam string
|
||||||
MpesaOnrampBearerToken string
|
|
||||||
mpesaOnrampBase string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
CreateAccountURL string
|
CreateAccountURL string
|
||||||
TrackStatusURL string
|
TrackStatusURL string
|
||||||
BalanceURL string
|
BalanceURL string
|
||||||
TrackURL string
|
TrackURL string
|
||||||
TokenTransferURL string
|
TokenTransferURL string
|
||||||
VoucherHoldingsURL string
|
VoucherHoldingsURL string
|
||||||
VoucherTransfersURL string
|
VoucherTransfersURL string
|
||||||
VoucherDataURL string
|
VoucherDataURL string
|
||||||
PoolDepositURL string
|
PoolDepositURL string
|
||||||
PoolSwapQuoteURL string
|
PoolSwapQuoteURL string
|
||||||
PoolSwapURL string
|
PoolSwapURL string
|
||||||
TopPoolsURL string
|
TopPoolsURL string
|
||||||
RetrievePoolDetailsURL string
|
RetrievePoolDetailsURL string
|
||||||
PoolSwappableVouchersURL string
|
PoolSwappableVouchersURL string
|
||||||
SendSMSURL string
|
SendSMSURL string
|
||||||
AliasRegistrationURL string
|
AliasRegistrationURL string
|
||||||
AliasResolverURL string
|
AliasResolverURL string
|
||||||
ExternalSMSURL string
|
ExternalSMSURL string
|
||||||
AliasUpdateURL string
|
AliasUpdateURL string
|
||||||
CreditSendURL string
|
|
||||||
CreditSendReverseQuoteURL string
|
|
||||||
MpesaOnrampURL string
|
|
||||||
MpresaOnrampRatesURL string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func setBase() error {
|
func setBase() error {
|
||||||
@ -78,8 +68,6 @@ func setBase() error {
|
|||||||
externalSMSBase = env.GetEnv("EXTERNAL_SMS_BASE", "http://localhost:5035")
|
externalSMSBase = env.GetEnv("EXTERNAL_SMS_BASE", "http://localhost:5035")
|
||||||
BearerToken = env.GetEnv("BEARER_TOKEN", "")
|
BearerToken = env.GetEnv("BEARER_TOKEN", "")
|
||||||
IncludeStablesParam = env.GetEnv("INCLUDE_STABLES_PARAM", "false")
|
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)
|
_, err = url.Parse(custodialURLBase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -117,10 +105,6 @@ func LoadConfig() error {
|
|||||||
AliasResolverURL, _ = url.JoinPath(aliasEnsURLBase, AliasResolverPrefix)
|
AliasResolverURL, _ = url.JoinPath(aliasEnsURLBase, AliasResolverPrefix)
|
||||||
ExternalSMSURL, _ = url.JoinPath(externalSMSBase, ExternalSMSPrefix)
|
ExternalSMSURL, _ = url.JoinPath(externalSMSBase, ExternalSMSPrefix)
|
||||||
AliasUpdateURL, _ = url.JoinPath(aliasEnsURLBase, AliasUpdatePrefix)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
45
dev/api.go
45
dev/api.go
@ -587,10 +587,10 @@ func (das *DevAccountService) FetchVouchers(ctx context.Context, publicKey strin
|
|||||||
//TODO: Iterate over the account acc.Balances object
|
//TODO: Iterate over the account acc.Balances object
|
||||||
for _, voucher := range das.vouchers {
|
for _, voucher := range das.vouchers {
|
||||||
holdings = append(holdings, dataserviceapi.TokenHoldings{
|
holdings = append(holdings, dataserviceapi.TokenHoldings{
|
||||||
TokenAddress: voucher.Address,
|
TokenAddress: voucher.Address,
|
||||||
TokenSymbol: voucher.Symbol,
|
TokenSymbol: voucher.Symbol,
|
||||||
TokenDecimals: strconv.Itoa(voucher.Decimals),
|
TokenDecimals: strconv.Itoa(voucher.Decimals),
|
||||||
Balance: strconv.Itoa(int(defaultVoucherBalance)),
|
Balance: strconv.Itoa(int(defaultVoucherBalance)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,10 +861,10 @@ func (das *DevAccountService) GetPoolSwappableFromVouchers(ctx context.Context,
|
|||||||
}
|
}
|
||||||
for _, v := range p.Vouchers {
|
for _, v := range p.Vouchers {
|
||||||
swapFromList = append(swapFromList, dataserviceapi.TokenHoldings{
|
swapFromList = append(swapFromList, dataserviceapi.TokenHoldings{
|
||||||
TokenAddress: v.Address,
|
TokenAddress: v.Address,
|
||||||
TokenSymbol: v.Symbol,
|
TokenSymbol: v.Symbol,
|
||||||
TokenDecimals: string(defaultDecimals),
|
TokenDecimals: string(defaultDecimals),
|
||||||
Balance: fmt.Sprintf("%f", defaultVoucherBalance),
|
Balance: fmt.Sprintf("%f", defaultVoucherBalance),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,32 +907,3 @@ func (das *DevAccountService) CheckTokenInPool(ctx context.Context, poolAddress,
|
|||||||
CanSwapFrom: true,
|
CanSwapFrom: true,
|
||||||
}, nil
|
}, 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
32
go.mod
@ -1,38 +1,36 @@
|
|||||||
module git.grassecon.net/grassrootseconomics/sarafu-api
|
module git.grassecon.net/grassrootseconomics/sarafu-api
|
||||||
|
|
||||||
go 1.24.0
|
go 1.23.4
|
||||||
|
|
||||||
toolchain go1.24.6
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.defalsify.org/vise.git v0.2.3-0.20250204132233-2bffe532f21e
|
git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9
|
||||||
git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1
|
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d
|
||||||
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2
|
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2
|
||||||
github.com/gofrs/uuid v4.4.0+incompatible
|
github.com/gofrs/uuid v4.4.0+incompatible
|
||||||
github.com/grassrootseconomics/eth-custodial v1.12.0-rc
|
github.com/grassrootseconomics/eth-custodial v1.3.0-beta
|
||||||
github.com/grassrootseconomics/ussd-data-service v1.10.1-beta
|
github.com/grassrootseconomics/ussd-data-service v1.6.0-beta
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.9.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
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/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/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // 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/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
github.com/joho/godotenv v1.5.1 // 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/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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.13.1 // 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
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
golang.org/x/crypto v0.45.0 // indirect
|
golang.org/x/crypto v0.32.0 // indirect
|
||||||
golang.org/x/sync v0.18.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/text v0.31.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
gopkg.in/leonelquinteros/gotext.v1 v1.3.1 // indirect
|
gopkg.in/leonelquinteros/gotext.v1 v1.3.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
67
go.sum
67
go.sum
@ -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.20250120121301-10739fb4a8c9 h1:sPcqXQcywxA8W3W+9qQncLPmsrgqTIlec7vmD4/7vyA=
|
||||||
git.defalsify.org/vise.git v0.2.3-0.20250204132233-2bffe532f21e/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
|
git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
|
||||||
git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1 h1:eppylYmQ9izyar0HIhb0Qbnat33EJYaH+5bFpp2PSkg=
|
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d h1:5mzLas+jxTUtusOKx4XvU+n2QvrV/mH17MnJRy46siQ=
|
||||||
git.grassecon.net/grassrootseconomics/common v0.9.0-beta.1/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
|
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
|
||||||
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2 h1:YFztSsexCUgFo6M0tbngRwYdgJd3LQV3RO/Jw09u3+k=
|
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2 h1:ON77G5K0JNuwPb5JT/hRfF6G6+xstlBQgEIEzWydnhg=
|
||||||
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.2/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w=
|
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250122123424-6749c632b0a2/go.mod h1:pjKp9L/ZsWW3kMB0UoIl1yv9TBIuU33mn9Aghxp7vGk=
|
||||||
github.com/barbashov/iso639-3 v1.0.0 h1:qCp1hUzZT8C8yHcdDo4sZQg2jHEaX6LF5H/dF9ba0qs=
|
github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c h1:H9Nm+I7Cg/YVPpEV1RzU3Wq2pjamPc/UtHDgItcb7lE=
|
||||||
github.com/barbashov/iso639-3 v1.0.0/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U=
|
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.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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
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 h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
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.3.0-beta h1:twrMBhl89GqDUL9PlkzQxMP/6OST1BByrNDj+rqXDmU=
|
||||||
github.com/grassrootseconomics/eth-custodial v1.12.0-rc/go.mod h1:s/vacSWFiVO7FDv76EID8sQvdT1vq+3GcWZUgU6N618=
|
github.com/grassrootseconomics/eth-custodial v1.3.0-beta/go.mod h1:7uhRcdnJplX4t6GKCEFkbeDhhjlcaGJeJqevbcvGLZo=
|
||||||
github.com/grassrootseconomics/ussd-data-service v1.10.1-beta h1:ZrRn7gv4MVSg67hmSdiii/Y86PUIvhxtqc2luAjlA7o=
|
github.com/grassrootseconomics/ussd-data-service v1.2.0-beta h1:fn1gwbWIwHVEBtUC2zi5OqTlfI/5gU1SMk0fgGixIXk=
|
||||||
github.com/grassrootseconomics/ussd-data-service v1.10.1-beta/go.mod h1:Uigrnnwj0vaTz2az3VwHmAG7xpJgQWYTcLudLh6Zc1I=
|
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 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo=
|
||||||
github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y=
|
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 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
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 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
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.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
|
||||||
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
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 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
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/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 h1:0Q3H0YXzMHiciXtRcM+j0jiCe8WKPQHoRgQiRTnfcLY=
|
||||||
github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a/go.mod h1:CdTTBOYzS5E4mWS1N8NWP6AHI19MP0A2B18n3hLzRMk=
|
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.3.0 h1:DqT7fk0OCK6H0GvqtcMsLpv8cIwWqdxWgfZNLeHCb/s=
|
||||||
github.com/pashagolub/pgxmock/v4 v4.7.0/go.mod h1:9L57pC193h2aKRHVyiiE817avasIPZnPwPlw3JczWvM=
|
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 h1:8jckE9KcyNHgyv/VPoaljvKZE0Rqr8+dPVYH6rfNr9I=
|
||||||
github.com/peteole/testdata-loader v0.3.0/go.mod h1:Mt0ZbRtb56u8SLJpNP+BnQbENljMorYBpqlvt3cS83U=
|
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=
|
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 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
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.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
|
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.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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
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 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
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.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
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 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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
|||||||
@ -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"`
|
|
||||||
}
|
|
||||||
@ -20,13 +20,3 @@ type MaxLimitResult struct {
|
|||||||
type TokenInPoolResult struct {
|
type TokenInPoolResult struct {
|
||||||
CanSwapFrom bool `json:"canSwapFrom"`
|
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"`
|
|
||||||
}
|
|
||||||
|
|||||||
@ -30,8 +30,4 @@ type AccountService interface {
|
|||||||
PoolSwap(ctx context.Context, amount, from, fromTokenAddress, poolAddress, toTokenAddress string) (*models.PoolSwapResult, 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)
|
GetSwapFromTokenMaxLimit(ctx context.Context, poolAddress, fromTokenAddress, toTokenAddress, publicKey string) (*models.MaxLimitResult, error)
|
||||||
CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, 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)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.defalsify.org/vise.git/logging"
|
"git.defalsify.org/vise.git/logging"
|
||||||
@ -22,25 +23,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
aliasRegex = regexp.MustCompile("^\\+?[a-zA-Z0-9\\-_]+$")
|
||||||
logg = logging.NewVanilla().WithDomain("sarafu-api.devapi")
|
logg = logging.NewVanilla().WithDomain("sarafu-api.devapi")
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIError struct {
|
|
||||||
Code string
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
return e.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPAccountService struct {
|
type HTTPAccountService struct {
|
||||||
SS storage.StorageService
|
SS storage.StorageService
|
||||||
UseApi bool
|
UseApi bool
|
||||||
@ -361,7 +347,7 @@ func (as *HTTPAccountService) PoolDeposit(ctx context.Context, amount, from, poo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -519,10 +505,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
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -744,117 +730,12 @@ func (as *HTTPAccountService) SendPINResetSMS(ctx context.Context, admin, phone
|
|||||||
return nil
|
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
|
// TODO: remove eth-custodial api dependency
|
||||||
func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) {
|
func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) {
|
||||||
var okResponse api.OKResponse
|
var okResponse api.OKResponse
|
||||||
var errResponse api.ErrResponse
|
var errResponse api.ErrResponse
|
||||||
|
|
||||||
// Check if a custom Authorization token was provided
|
req.Header.Set("Authorization", "Bearer "+config.BearerToken)
|
||||||
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("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
// Log request
|
// Log request
|
||||||
@ -881,11 +762,7 @@ func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKRespons
|
|||||||
if err := json.Unmarshal(body, &errResponse); err != nil {
|
if err := json.Unmarshal(body, &errResponse); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return nil, errors.New(errResponse.Description)
|
||||||
return nil, &APIError{
|
|
||||||
Code: errResponse.ErrCode,
|
|
||||||
Description: errResponse.Description,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(body, &okResponse); err != nil {
|
if err := json.Unmarshal(body, &okResponse); err != nil {
|
||||||
@ -893,7 +770,7 @@ func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKRespons
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(okResponse.Result) == 0 {
|
if len(okResponse.Result) == 0 {
|
||||||
return nil, errors.New("empty api result")
|
return nil, errors.New("Empty api result")
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := json.Marshal(okResponse.Result)
|
v, err := json.Marshal(okResponse.Result)
|
||||||
|
|||||||
@ -120,23 +120,3 @@ func (m MockAccountService) CheckTokenInPool(ctx context.Context, poolAddress, t
|
|||||||
args := m.Called(poolAddress, tokenAddress)
|
args := m.Called(poolAddress, tokenAddress)
|
||||||
return args.Get(0).(*models.TokenInPoolResult), args.Error(1)
|
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)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import (
|
|||||||
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
|
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is used in the menu traversal tests
|
|
||||||
|
|
||||||
type TestAccountService struct {
|
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) {
|
func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) {
|
||||||
return []dataserviceapi.TokenHoldings{
|
return []dataserviceapi.TokenHoldings{
|
||||||
{
|
dataserviceapi.TokenHoldings{
|
||||||
TokenAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee",
|
TokenAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee",
|
||||||
TokenSymbol: "SRF",
|
TokenSymbol: "SRF",
|
||||||
TokenDecimals: "6",
|
TokenDecimals: "6",
|
||||||
Balance: "2745987",
|
Balance: "2745987",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
TokenAddress: "0x3f195a3F68BF4c6D49748eFa033a00C6634fF311",
|
|
||||||
TokenSymbol: "USD",
|
|
||||||
TokenDecimals: "6",
|
|
||||||
Balance: "4269100",
|
|
||||||
},
|
|
||||||
}, nil
|
}, 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) {
|
func (m TestAccountService) CheckTokenInPool(ctx context.Context, poolAddress, tokenAddress string) (*models.TokenInPoolResult, error) {
|
||||||
return &models.TokenInPoolResult{}, nil
|
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
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user