Documentation
¶
Overview ¶
Package weeasycrypto is the official Go SDK for the WeEasyCrypto tenant API: deposit addresses, balances, deposits, withdrawals, and signed webhooks. Zero dependencies outside the standard library.
Amounts are always decimal strings, never floats. requestId is YOUR idempotency key — persist it before calling, the SDK never generates one.
Index ¶
- Constants
- func FormatAmount(raw *big.Int, decimals int) string
- func ParseAmount(human string, decimals int) (*big.Int, error)
- type APIError
- type AddressesService
- func (s *AddressesService) Create(ctx context.Context, params CreateAddressParams) (*DepositAddress, error)
- func (s *AddressesService) Iterate(ctx context.Context, params PaginationParams) iter.Seq2[DepositAddress, error]
- func (s *AddressesService) List(ctx context.Context, params PaginationParams) (*Page[DepositAddress], error)
- type Balance
- type BalancesService
- type Chain
- type ChainFamily
- type ChainToken
- type ChainsService
- type Client
- type CreateAddressParams
- type CreateWithdrawalBatchParams
- type CreateWithdrawalParams
- type Deposit
- type DepositAddress
- type DepositEventData
- type DepositStatus
- type DepositsService
- type Hooks
- type InvalidAmountError
- type ListDepositsParams
- type ListWithdrawalsParams
- type NetworkError
- type Options
- type Page
- type PaginationParams
- type SweepEventData
- type TimeoutError
- type VerifyOptions
- type WaitOptions
- type WebhookEvent
- type WebhookVerificationError
- type WebhooksService
- type Withdrawal
- type WithdrawalBatch
- type WithdrawalBatchItem
- type WithdrawalEventData
- type WithdrawalStatus
- type WithdrawalsService
- func (s *WithdrawalsService) Create(ctx context.Context, params CreateWithdrawalParams) (*Withdrawal, error)
- func (s *WithdrawalsService) CreateBatch(ctx context.Context, params CreateWithdrawalBatchParams) (*WithdrawalBatch, error)
- func (s *WithdrawalsService) Get(ctx context.Context, id string) (*Withdrawal, error)
- func (s *WithdrawalsService) Iterate(ctx context.Context, params ListWithdrawalsParams) iter.Seq2[Withdrawal, error]
- func (s *WithdrawalsService) List(ctx context.Context, params ListWithdrawalsParams) (*Page[Withdrawal], error)
- func (s *WithdrawalsService) WaitUntilFinal(ctx context.Context, id string, opts WaitOptions) (*Withdrawal, error)
Constants ¶
const ( CodeBadRequest = "BAD_REQUEST" CodeInvalidAmount = "INVALID_AMOUNT" CodeForbidden = "FORBIDDEN" CodeNotFound = "NOT_FOUND" CodeDuplicateRequest = "DUPLICATE_REQUEST" CodeStateConflict = "STATE_CONFLICT" CodeValidationFailed = "VALIDATION_FAILED" CodeInsufficientBalance = "INSUFFICIENT_BALANCE" CodeRateLimited = "RATE_LIMITED" CodeInternalError = "INTERNAL_ERROR" )
Stable error codes emitted by the API envelope. The server may introduce new codes at any time — always compare against the constant, never enumerate exhaustively.
Variables ¶
This section is empty.
Functions ¶
func FormatAmount ¶
FormatAmount converts a minimal-unit *big.Int back to a human-readable decimal string (trailing zeros trimmed).
FormatAmount(big.NewInt(100500000), 6) // "100.5"
func ParseAmount ¶
ParseAmount converts a human-readable decimal string to a minimal-unit *big.Int. Strict: rejects negatives, exponents, and more fractional digits than decimals — the same rules the server applies (400 INVALID_AMOUNT).
ParseAmount("100.5", 6) // 100500000
Types ¶
type APIError ¶
type APIError struct {
Status int
Code string
Message string
// RetryAfter is the suggested wait from the Retry-After header on 429
// responses; 0 when the server didn't send one.
RetryAfter time.Duration
}
APIError is a non-2xx API response. Code is the stable machine-readable error code from the response envelope; Status is the HTTP status. Match with errors.As and then on Status / Code:
var apiErr *weeasycrypto.APIError
if errors.As(err, &apiErr) && apiErr.IsDuplicateRequest() { … }
func (*APIError) IsDuplicateRequest ¶
IsDuplicateRequest reports whether a 409 means the requestId was already used: the withdrawal exists and the retry was idempotent-safe. Treat it as success-shaped — look the withdrawal up via your own requestId → id mapping rather than surfacing an error.
type AddressesService ¶
type AddressesService struct {
// contains filtered or unexported fields
}
AddressesService is /v1/addresses — deposit address issuance and listing.
func (*AddressesService) Create ¶
func (s *AddressesService) Create(ctx context.Context, params CreateAddressParams) (*DepositAddress, error)
Create issues a deposit address.
Not retried automatically on network errors (no idempotency key): if the outcome is unknown, List recent addresses before creating again — duplicate addresses carry no fund risk but pollute your label bookkeeping.
func (*AddressesService) Iterate ¶
func (s *AddressesService) Iterate(ctx context.Context, params PaginationParams) iter.Seq2[DepositAddress, error]
Iterate auto-paginates over all addresses.
func (*AddressesService) List ¶
func (s *AddressesService) List(ctx context.Context, params PaginationParams) (*Page[DepositAddress], error)
List returns addresses, newest first.
type Balance ¶
type Balance struct {
ChainKey string `json:"chainKey"`
Symbol string `json:"symbol"`
TokenID string `json:"tokenId"`
Available string `json:"available"`
Locked string `json:"locked"`
}
Balance is a per-token balance. Available / Locked are human-readable decimal strings — convert with ParseAmount, never with strconv.ParseFloat.
type BalancesService ¶
type BalancesService struct {
// contains filtered or unexported fields
}
BalancesService is /v1/balances — per-token balances.
type Chain ¶
type Chain struct {
Key string `json:"key"`
Name string `json:"name"`
Family ChainFamily `json:"family"`
ChainID *int64 `json:"chainId"`
NativeSymbol string `json:"nativeSymbol"`
NativeDecimals int `json:"nativeDecimals"`
RequiredConfirmations int `json:"requiredConfirmations"`
ExplorerURL *string `json:"explorerUrl"`
Tokens []ChainToken `json:"tokens"`
}
Chain is an enabled chain. ChainID is only meaningful for the EVM family — nil elsewhere.
type ChainFamily ¶
type ChainFamily string
ChainFamily determines address format and derivation scheme.
const ( FamilyEVM ChainFamily = "EVM" FamilyTRON ChainFamily = "TRON" FamilyBTC ChainFamily = "BTC" FamilySOL ChainFamily = "SOL" FamilyTON ChainFamily = "TON" )
type ChainToken ¶
type ChainToken struct {
ID string `json:"id"`
Symbol string `json:"symbol"`
Name string `json:"name"`
ContractAddress *string `json:"contractAddress"`
Decimals int `json:"decimals"`
MinDeposit string `json:"minDeposit"`
}
ChainToken is an enabled token on a chain. ContractAddress is nil for native coins; MinDeposit is a human decimal string.
type ChainsService ¶
type ChainsService struct {
// contains filtered or unexported fields
}
ChainsService is /v1/chains — enabled chains and their tokens.
type Client ¶
type Client struct {
Addresses *AddressesService
Balances *BalancesService
Chains *ChainsService
Deposits *DepositsService
Withdrawals *WithdrawalsService
Webhooks *WebhooksService
// contains filtered or unexported fields
}
Client is the WeEasyCrypto tenant-API client.
cv, err := weeasycrypto.New(weeasycrypto.Options{
BaseURL: "https://api.example.com",
APIKey: os.Getenv("WEEASYCRYPTO_API_KEY"), // keyId, e.g. "ck_…"
PrivateKey: os.Getenv("WEEASYCRYPTO_PRIVATE_KEY"), // hex Ed25519 seed
})
addr, err := cv.Addresses.Create(ctx, weeasycrypto.CreateAddressParams{Label: "user-42", ChainKey: "tron"})
type CreateAddressParams ¶
type CreateAddressParams struct {
Label string `json:"label,omitempty"`
ChainKey string `json:"chainKey,omitempty"`
}
CreateAddressParams — both fields optional. ChainKey decides the address family (omitted ⇒ EVM).
type CreateWithdrawalBatchParams ¶
type CreateWithdrawalBatchParams struct {
RequestID string `json:"requestId"`
Items []WithdrawalBatchItem `json:"items"`
}
CreateWithdrawalBatchParams creates 1..200 withdrawals under one batch-level idempotency key (same discipline as CreateWithdrawalParams).
type CreateWithdrawalParams ¶
type CreateWithdrawalParams struct {
RequestID string `json:"requestId"`
ChainKey string `json:"chainKey"`
TokenSymbol string `json:"tokenSymbol"`
To string `json:"to"`
Amount string `json:"amount"`
}
CreateWithdrawalParams — RequestID is YOUR idempotency key (max 128 chars). Persist it in your own database BEFORE calling: replaying the same RequestID after a crash can never double-spend. The SDK deliberately does not generate one for you. A 409 DUPLICATE_REQUEST response means the withdrawal already exists and is a safety signal, not a failure. Amount is a human-readable decimal STRING, e.g. "100.5" — never a float.
type Deposit ¶
type Deposit struct {
ID string `json:"id"`
ChainKey string `json:"chainKey"`
TokenSymbol string `json:"tokenSymbol"`
Address string `json:"address"`
TxHash string `json:"txHash"`
LogIndex int `json:"logIndex"`
FromAddress *string `json:"fromAddress"`
Amount string `json:"amount"`
AmountRaw string `json:"amountRaw"`
BlockNumber string `json:"blockNumber"`
Status DepositStatus `json:"status"`
ConfirmedAt *string `json:"confirmedAt"`
CreatedAt string `json:"createdAt"`
}
Deposit is a detected deposit. FromAddress is nil on BTC (multi-input txs have no single payer); LogIndex is the vout on BTC. Tx hashes are chain-native (no 0x prefix on TRON/BTC). Amount is a human decimal string, AmountRaw a minimal-unit integer string, BlockNumber a decimal string (may exceed int64 on some chains — kept as string).
type DepositAddress ¶
type DepositAddress struct {
ID string `json:"id"`
Address string `json:"address"`
Family ChainFamily `json:"family"`
// Index is the HD derivation index. Same index + same family ⇒ same address.
Index int `json:"index"`
Label *string `json:"label"`
CreatedAt string `json:"createdAt"`
}
DepositAddress is a deposit address issued to your tenant. Address is rendered in the chain-native display format (EVM = EIP-55 checksum, TRON = base58, SOL = base58 case-sensitive, TON = base64url case-sensitive).
type DepositEventData ¶
type DepositEventData struct {
DepositID string `json:"depositId"`
ChainKey string `json:"chainKey"`
TxHash string `json:"txHash"`
LogIndex int `json:"logIndex"`
Address string `json:"address"`
FromAddress *string `json:"fromAddress"`
TokenID string `json:"tokenId"`
TokenSymbol string `json:"tokenSymbol"`
Amount string `json:"amount"`
AmountRaw string `json:"amountRaw"`
BlockNumber string `json:"blockNumber"`
Status DepositStatus `json:"status"`
Family ChainFamily `json:"family,omitempty"`
}
DepositEventData is the payload of deposit.detected / deposit.confirmed. Family is additive and may be empty if chain config lookup degraded.
type DepositStatus ¶
type DepositStatus string
DepositStatus values. The server may add new statuses over time.
const ( DepositPending DepositStatus = "PENDING" DepositConfirmed DepositStatus = "CONFIRMED" DepositOrphaned DepositStatus = "ORPHANED" DepositDust DepositStatus = "DUST" )
type DepositsService ¶
type DepositsService struct {
// contains filtered or unexported fields
}
DepositsService is /v1/deposits — deposit history.
func (*DepositsService) Iterate ¶
func (s *DepositsService) Iterate(ctx context.Context, params ListDepositsParams) iter.Seq2[Deposit, error]
Iterate auto-paginates over deposits.
func (*DepositsService) List ¶
func (s *DepositsService) List(ctx context.Context, params ListDepositsParams) (*Page[Deposit], error)
List returns deposits, newest first.
type Hooks ¶
type Hooks struct {
OnRequest func(method, path string, attempt int)
OnResponse func(method, path string, status int, duration time.Duration, attempt int)
OnRetry func(method, path string, attempt int, delay time.Duration, reason string)
}
Hooks are observability callbacks — wire them to your own logger/tracer. The SDK never logs by itself.
type InvalidAmountError ¶
type InvalidAmountError struct{ Message string }
InvalidAmountError is returned by ParseAmount / FormatAmount on malformed input.
func (*InvalidAmountError) Error ¶
func (e *InvalidAmountError) Error() string
type ListDepositsParams ¶
type ListDepositsParams struct {
PaginationParams
Status DepositStatus
ChainKey string
TokenSymbol string
Address string
TxHash string
}
ListDepositsParams filters the deposit listing. Zero values are omitted.
type ListWithdrawalsParams ¶
type ListWithdrawalsParams struct {
PaginationParams
Status WithdrawalStatus
ChainKey string
}
ListWithdrawalsParams filters the withdrawal listing.
type NetworkError ¶
NetworkError means the request never produced an HTTP response (DNS failure, connection reset, timeout). For withdrawal calls this is safe to retry with the SAME requestId — the server-side idempotency key guarantees at most one withdrawal.
func (*NetworkError) Error ¶
func (e *NetworkError) Error() string
func (*NetworkError) Unwrap ¶
func (e *NetworkError) Unwrap() error
type Options ¶
type Options struct {
// BaseURL is the API origin, e.g. "https://api.example.com". Path
// prefixes are honored.
BaseURL string
// APIKey is the key ID as issued (e.g. "ck_…") — a public identifier;
// the secret part is PrivateKey.
APIKey string
// PrivateKey is the hex 32-byte Ed25519 seed generated in the merchant
// portal when the key was issued. It signs every request; the platform
// holds only the matching public key. Server-side only — never ship it
// to a browser or mobile app.
PrivateKey string
// WebhookPublicKey is the tenant's webhook verification public key (hex,
// 32 bytes) — copy it from the merchant portal (Settings → Integrations).
// Not a secret. Required only if you use Client.Webhooks.
WebhookPublicKey string
// Timeout per request. Default 30s.
Timeout time.Duration
// MaxRetries for retryable failures. Default 3; set DisableRetries to
// turn retries off entirely.
MaxRetries int
DisableRetries bool
// RetryBaseDelay is the base backoff delay (full jitter, exponential).
// Default 500ms.
RetryBaseDelay time.Duration
// WebhookTolerance is the accepted webhook timestamp skew. Default 300s.
WebhookTolerance time.Duration
// HTTPClient overrides the default http.Client — proxies, test stubs.
HTTPClient *http.Client
Hooks Hooks
}
Options configures a Client.
type Page ¶
type Page[T any] struct { Items []T `json:"items"` Total int `json:"total"` Page int `json:"page"` PageSize int `json:"pageSize"` }
Page is one page of results, mirroring the server's pagination shape.
type PaginationParams ¶
PaginationParams selects a page. Page is 1-based (default 1); PageSize is 1..200 (default 20). Zero values are omitted.
type SweepEventData ¶
type SweepEventData struct {
SweepJobID string `json:"sweepJobId"`
ChainKey string `json:"chainKey"`
Address string `json:"address"`
Token string `json:"token"`
Amount string `json:"amount"`
AmountRaw string `json:"amountRaw"`
TxHash string `json:"txHash"`
Family ChainFamily `json:"family,omitempty"`
}
SweepEventData is the payload of sweep.completed.
type TimeoutError ¶
type TimeoutError struct{ Message string }
TimeoutError means a client-side wait (e.g. Withdrawals.WaitUntilFinal) exceeded its time budget. The withdrawal keeps processing server-side.
func (*TimeoutError) Error ¶
func (e *TimeoutError) Error() string
type VerifyOptions ¶
type VerifyOptions struct {
Tolerance time.Duration
// Now is the current unix time in seconds — injectable for tests.
Now int64
}
VerifyOptions overrides per call. Zero values mean the client-level defaults (tolerance 300s, wall clock).
type WaitOptions ¶
WaitOptions configures WaitUntilFinal. Zero values mean the defaults: 5s interval, 10min timeout.
type WebhookEvent ¶
type WebhookEvent struct {
// ID is globally unique, e.g. "deposit.confirmed:<depositId>" — use for dedup.
ID string `json:"id"`
Type string `json:"type"`
CreatedAt string `json:"createdAt"`
Data json.RawMessage `json:"data"`
}
WebhookEvent is a verified webhook event. Known types: deposit.detected, deposit.confirmed, withdrawal.completed, withdrawal.failed, sweep.completed. New event types may be introduced at any time — they parse fine and Data stays available as raw JSON (evolution contract: ignore what you don't know, never reject).
func (*WebhookEvent) DepositEventData ¶
func (e *WebhookEvent) DepositEventData() (*DepositEventData, error)
DepositEventData decodes the payload of deposit.detected / deposit.confirmed.
func (*WebhookEvent) SweepEventData ¶
func (e *WebhookEvent) SweepEventData() (*SweepEventData, error)
SweepEventData decodes the payload of sweep.completed.
func (*WebhookEvent) WithdrawalEventData ¶
func (e *WebhookEvent) WithdrawalEventData() (*WithdrawalEventData, error)
WithdrawalEventData decodes the payload of withdrawal.completed / withdrawal.failed.
type WebhookVerificationError ¶
type WebhookVerificationError struct{ Message string }
WebhookVerificationError is a webhook signature mismatch, malformed header, or timestamp outside tolerance.
func (*WebhookVerificationError) Error ¶
func (e *WebhookVerificationError) Error() string
type WebhooksService ¶
type WebhooksService struct {
// contains filtered or unexported fields
}
WebhooksService verifies and parses signed webhooks. The platform signs each delivery with a per-tenant Ed25519 key (`v1a`); verification needs only the tenant's public key — no shared secret.
// Raw body must be the exact bytes received — do not re-serialize JSON.
event, err := cv.Webhooks.Parse(rawBody, r.Header.Get("X-Webhook-Signature"))
func (*WebhooksService) Parse ¶
func (s *WebhooksService) Parse(rawBody []byte, signatureHeader string, opts ...VerifyOptions) (*WebhookEvent, error)
Parse verifies then decodes the event. Unknown event types do NOT error — they surface with Type as-is and Data as raw JSON, so new platform events never break your endpoint.
func (*WebhooksService) Verify ¶
func (s *WebhooksService) Verify(rawBody []byte, signatureHeader string, opts ...VerifyOptions) error
Verify checks the `X-Webhook-Signature: t={ts},v1a={hex}` header against the raw body with the tenant's Ed25519 public key. Returns *WebhookVerificationError on any mismatch.
type Withdrawal ¶
type Withdrawal struct {
ID string `json:"id"`
RequestID string `json:"requestId"`
BatchID *string `json:"batchId"`
ChainKey string `json:"chainKey"`
TokenSymbol string `json:"tokenSymbol"`
To string `json:"to"`
Amount string `json:"amount"`
AmountRaw string `json:"amountRaw"`
Status WithdrawalStatus `json:"status"`
TxHash *string `json:"txHash"`
FailReason *string `json:"failReason"`
ConfirmedAt *string `json:"confirmedAt"`
CreatedAt string `json:"createdAt"`
}
Withdrawal — TxHash is non-nil only once the transaction has been broadcast; ConfirmedAt only once confirmed.
type WithdrawalBatch ¶
type WithdrawalBatch struct {
BatchID string `json:"batchId"`
RequestID string `json:"requestId"`
CreatedAt string `json:"createdAt"`
Withdrawals []Withdrawal `json:"withdrawals"`
}
WithdrawalBatch is the result of a batch creation.
type WithdrawalBatchItem ¶
type WithdrawalBatchItem struct {
ChainKey string `json:"chainKey"`
TokenSymbol string `json:"tokenSymbol"`
To string `json:"to"`
Amount string `json:"amount"`
}
WithdrawalBatchItem is one entry of CreateWithdrawalBatchParams.
type WithdrawalEventData ¶
type WithdrawalEventData struct {
ID string `json:"id"`
RequestID string `json:"requestId"`
ChainKey string `json:"chainKey"`
TokenSymbol string `json:"tokenSymbol"`
To string `json:"to"`
Amount string `json:"amount"`
AmountRaw string `json:"amountRaw"`
TxHash *string `json:"txHash"`
FailReason *string `json:"failReason"`
Family ChainFamily `json:"family,omitempty"`
}
WithdrawalEventData is the payload of withdrawal.completed / withdrawal.failed.
type WithdrawalStatus ¶
type WithdrawalStatus string
WithdrawalStatus values. Terminal: CONFIRMED, FAILED, REJECTED, CANCELED.
const ( WithdrawalPendingApproval WithdrawalStatus = "PENDING_APPROVAL" WithdrawalApproved WithdrawalStatus = "APPROVED" WithdrawalQueued WithdrawalStatus = "QUEUED" WithdrawalBroadcast WithdrawalStatus = "BROADCAST" WithdrawalConfirmed WithdrawalStatus = "CONFIRMED" WithdrawalRejected WithdrawalStatus = "REJECTED" WithdrawalCanceled WithdrawalStatus = "CANCELED" WithdrawalFailed WithdrawalStatus = "FAILED" )
func (WithdrawalStatus) IsFinal ¶
func (s WithdrawalStatus) IsFinal() bool
IsFinal reports whether the status is terminal.
type WithdrawalsService ¶
type WithdrawalsService struct {
// contains filtered or unexported fields
}
WithdrawalsService is /v1/withdrawals + /v1/withdrawal-batches — the money path.
func (*WithdrawalsService) Create ¶
func (s *WithdrawalsService) Create(ctx context.Context, params CreateWithdrawalParams) (*Withdrawal, error)
Create creates a withdrawal. PERSIST params.RequestID IN YOUR OWN DATABASE BEFORE CALLING — it is the idempotency key that makes crash-replay safe. Network errors on this call are auto-retried with the same RequestID (can never double-spend); a 409 with IsDuplicateRequest() == true means an earlier attempt already succeeded.
func (*WithdrawalsService) CreateBatch ¶
func (s *WithdrawalsService) CreateBatch(ctx context.Context, params CreateWithdrawalBatchParams) (*WithdrawalBatch, error)
CreateBatch creates up to 200 withdrawals under one batch-level RequestID (same idempotency discipline as Create).
func (*WithdrawalsService) Get ¶
func (s *WithdrawalsService) Get(ctx context.Context, id string) (*Withdrawal, error)
Get fetches one withdrawal by its server-side id.
func (*WithdrawalsService) Iterate ¶
func (s *WithdrawalsService) Iterate(ctx context.Context, params ListWithdrawalsParams) iter.Seq2[Withdrawal, error]
Iterate auto-paginates over withdrawals.
func (*WithdrawalsService) List ¶
func (s *WithdrawalsService) List(ctx context.Context, params ListWithdrawalsParams) (*Page[Withdrawal], error)
List returns withdrawals, newest first. Filters: Status, ChainKey.
func (*WithdrawalsService) WaitUntilFinal ¶
func (s *WithdrawalsService) WaitUntilFinal(ctx context.Context, id string, opts WaitOptions) (*Withdrawal, error)
WaitUntilFinal polls Get(id) until the withdrawal reaches a terminal status (CONFIRMED | FAILED | REJECTED | CANCELED). Pure client-side polling — webhooks (withdrawal.completed / withdrawal.failed) are the push-based alternative. Returns *TimeoutError if the budget is exceeded; the withdrawal keeps processing server-side.