web3-banking-system-sdk
v1.0.6
Published
TypeScript SDK used for interacting with the Web3 applications that uses Banking System API.
Readme
web3-banking-system-sdk
TypeScript SDK for building Web3 applications on top of the Banking System API.
It wraps the banking REST API (users, accounts, transactions, orders, organizations, programs, promotions) and the chain's Cosmos REST gateway (balances, staking, rewards) behind one typed, promise-based client — with session credentials, headers, payload shaping and response normalization handled for you.
- Typed end to end — every request payload and response body has a type.
- One entry point —
new API(config, errorHandler)exposes every domain. - Session handled for you — access tokens, device and installation IDs live in encrypted cookies and are injected into each request.
- Never rejects on API errors — failures come back as a normalized response object.
- Tree-shakeable —
sideEffects: false, plus per-domain deep imports.
Installation
npm install web3-banking-system-sdkRequirements
| | |
|---|---|
| Node.js | 18+ (CI builds and publishes on 24) |
| TypeScript | 5.x — the package ships ES2022 ESM output; use moduleResolution: "bundler" or "node16" |
| Runtime | Browser-first. Credential storage uses the CookieStore API with a document.cookie fallback; under Node those reads return empty and requests go out unauthenticated. |
Runtime dependencies (axios, dayjs, js-cookie, qs, uuid, psl,
ua-parser-js) ship as regular dependencies — nothing extra to install.
Quick start
import { API } from "web3-banking-system-sdk";
const api = new API(
{
baseUrl: "https://api.example.com/", // banking REST API
nodeUrl: "https://node.example.com/", // Cosmos REST gateway
programId: "1001", // your program identifier
lang: "en",
domain: ".example.com", // cookie scope (shared across subdomains)
},
(error) => console.error("[sdk]", error), // called for every transport error
);
// 1. Authenticate — credentials are persisted to encrypted cookies on success
const login = await api.auth.loginUserCredentials({
email: "[email protected]",
password: "••••••••",
installationId: "<installation-id>",
});
if (!login.success) {
console.warn(login.message);
return;
}
// 2. Subsequent calls pick up the stored credentials automatically
const user = await api.user.getUser();
const account = await api.account.get(user.data.account[0].info.id);
// 3. End the session (logs the device out, then clears cookies)
await api.logout();Configuration
type APIConfig = {
baseUrl: string; // banking REST API base URL
nodeUrl: string; // blockchain (Cosmos REST) base URL
programId: string; // namespaces cookies, sent with auth payloads
lang: string; // default language header ("i18next" in localStorage wins if set)
domain: string; // cookie domain scope
};
type ErrorHandler = (error: unknown) => void;api.context exposes live config — getBaseUrl(), getNodeUrl(),
getProgramId(), getLang() / setLang(), getGeoHelper(). Call setLang()
when the user switches language mid-session; services read it at request time,
not at construction.
Responses and error handling
Every call resolves to an ApiResponse<T>. Nothing rejects — transport errors
are routed to your errorHandler and converted into a normal response.
type ApiResponse<T> = {
data: T; // typed response body, always including `result`
success: boolean; // result code is Approved (or Create_User_Completed_Partially)
message: string; // result.friendly_message — safe to show to users
error: string | null; // result.message when the HTTP status is >= 400
};const response = await api.user.getAddress();
if (response.success) {
render(response.data);
} else {
toast(response.message);
}For finer-grained checks, use the result helpers and codes:
import { ResultHelper, SystemResponses } from "web3-banking-system-sdk";
ResultHelper.isApproved(response.data.result); // "0000" / partial-create
ResultHelper.isAuthenticated(response.data.result); // not Invalid_Token / Token_Is_Not_Active
if (response.data.result.code === SystemResponses.Invalid_Token) {
// re-authenticate with stored device credentials, then retry
}Session lifecycle is the consumer's job
The SDK does not refresh tokens or retry on expiry. On Invalid_Token /
Token_Is_Not_Active, call api.auth.loginDeviceCredentials(...) and retry the
original call; if that fails, call api.logout() and redirect to your login
route. A thin wrapper around your SDK calls is the usual place for this.
Architecture
your app
│
▼
API ──────────► Proxy ──────────► Service ──────────► HTTP
one instance, orchestration: transport: axios
every domain `fill*` payload endpoint URLs,
shaping, cookie interceptors,
writes, limited request flags
token mintingAPI— builds oneClientContextProvider, oneCookiesHelper, and every proxy from them.- Proxy (
api.user,api.auth, …) — the consumer-facing surface. Takes a friendlyI…Dataobject, runs it through afill*function to produce the wire payload, and persists credentials after successful auth calls. - Service — a pure axios wrapper per endpoint. Request interceptors inject
Authorization,Source_Id,Time_Zone, language, installation ID and geo coordinates; the response interceptor normalizes the body and wraps it inApiResponse<T>. ClientContextProvider— source of truth for config, read through getters at the moment a request is issued, so fresh values always win.CookiesHelper— AES-256-CBC-encryptedIID,USR,DEK,access_tokenandjwt_token, namespaced perprogramId. Full reference:docs/cookies-helper-reference.md.
Domain reference
api.auth
| Method | Purpose |
|---|---|
| loginUserCredentials(data) | Email/password login |
| loginDeviceCredentials(data) | Silent re-login from stored device credentials |
| loginGoogleCredentials(data) | Google OAuth login |
| generateLimitedToken(data) | Mint a pre-auth (limited) token |
All three login methods write credential cookies when the result is approved.
api.user
The widest surface — profile, security, contact details, documents, devices.
- Reads —
getUser,getPersonalInfo,getPreferences,getSecurity,getEmail,getPhone,getAddress,getBankAccount,getCreditCard,getIdentification,getDocuments,getAccount,getCurrency,getGroup,getExternalAuth,getHistory,getLatestHistory,getDeviceHistory,getSecurityOperations,getTermsAndConditions - Creates —
createUser,createUserWithGoogle,createEmail,createPhone,createAddress,createBankAccount,createCreditCard,createIdentification,createDevice,createCurrency,createTicket,createExternalAuth,uploadDocument,updateProfilePicture - Updates —
updateUser,updatePersonalInfo,updatePreferences,updateEmail,updatePhone,updateAddress,updateBankAccount,updateIdentification,updateDevice,updateExternalAuth,updateUserType,makeEmailPrimary,makePhonePrimary,makeAddressPrimary,makeBankAccountPrimary - Security —
securityAccess,sendEmailOTP,sendPhoneOTP,verifyEmail,verifyPhone,verifyDevice,verifySecurityData,confirmEmail,confirmPhone,confirmDevice,confirmSecurityData,resetPassword,resetSecurityCode,resetSecurityQuestions,resetSecurityData,validateSecurityCode,enrollGoogleAuth,activateGoogleAuth,deactivateGoogleAuth,deleteGoogleAuth - Deletes / logout —
deleteEmail,deletePhone,deleteAddress,deleteBankAccount,deleteIdentification,deleteDevice,logoutDevice
getAddress, getBankAccount and getIdentification always request
sensitive-data disclosure — there is no consumer flag to set.
api.account
| Method | Purpose |
|---|---|
| get(accountId) | Account details |
| getLimits(accountId) | Daily / monthly / yearly deposit, withdraw and transfer limits |
api.transaction
| Method | Purpose |
|---|---|
| inquiryTransaction(params) | Query transaction history |
| createSystemTransaction(data) | Internal ledger transaction |
| createBlockchainTransaction(data) | On-chain transaction |
| createBlockchainTransferTransaction(data) | On-chain transfer |
| createGatewayCryptoTransaction(data) | Crypto payment-gateway transaction |
api.limited — pre-authentication flows
Each method mints a fresh limited token automatically, so these work before a user is logged in.
checkForgetPassword, validateForgetPassword, confirmForgetPassword,
validateEmail, validatePhone, verifyEmail, verifyPhone, confirmEmail,
confirmPhone
api.order, api.organization, api.program, api.promotion
| Domain | Methods |
|---|---|
| order | createOrder |
| organization | getOrganization, createOrganization, updateOrganization, deleteOrganization, uploadDocument, userId |
| program | get, getSystemFeatures, getBin, getSignUp, getProgramSecurity |
| promotion | getPromotionByCode, getTwitterSpotlightPostIds, incrementPromotionParticipants |
Blockchain
Two deliberately separate surfaces.
api.blockchain — writes. Authenticated transactions submitted through the
banking backend in your program's context.
await api.blockchain.send({ /* IBlockchainSendRequestData */ });
await api.blockchain.multiSend({ /* IBlockchainMultiSendRequestData */ });
await api.blockchain.delegate({ /* IBlockchainDelegateRequestData */ });
await api.blockchain.undelegate({ /* IBlockchainUndelegateRequestData */ });BlockchainAPI — reads. Unauthenticated chain state straight off the Cosmos
REST gateway, with its own base URL.
import { BlockchainAPI } from "web3-banking-system-sdk/blockchain";
const chain = new BlockchainAPI(
{ baseUrl: "https://node.example.com/" },
console.error,
);
await chain.getBalance(address);
await chain.getSpendableBalances(address, { limit: 50, countTotal: true });
await chain.getBalanceAndFee(params); // balances + delegation + fee in one round trip
await chain.getTotalSupply();
await chain.getSupplyByDenom(denom);
await chain.getValidators();
await chain.getValidator(validatorAddress);
await chain.getDelegation(delegatorAddress, validatorAddress);
await chain.getDelegations(delegatorAddress);
await chain.getDelegatorValidators(delegatorAddress);
await chain.getStakingParams();
await chain.getDelegationRewards(delegatorAddress, validatorAddress);
await chain.getTotalRewards(delegatorAddress);
await chain.getAccount(address);Paginated reads take an optional PaginationParams (key, offset, limit,
countTotal, reverse), flattened into the gateway's dotted query params
(pagination.limit, …). Omit it and the node's defaults apply.
Helpers, constants and content
Exported from the package root (and from /helpers, /constants, /enums):
| Helper | Use |
|---|---|
| CookiesHelper | Encrypted credential cookies (IID, USR, DEK, tokens) |
| CipherHelper | AES-256-CBC encrypt / decrypt |
| StorageHelper, LocalStorageHelper | Storage abstraction |
| ResponseHelper, ResultHelper, AxiosHelper | Response normalization, result codes, header injection |
| DateTimeHelper | Client time zone and date formatting (dayjs) |
| DeviceHelper, ClientHelper | Device fingerprint and user-agent parsing |
| GeoHelper | IP / geo coordinates attached to requests |
| UserHelper | User-shape utilities |
Constants and reference data:
Endpoints,UserEndpoints,BcApiEndpoints,HeaderKeys,CookieKeys,SystemResponses- ~70 enums —
TransactionType,OrderStatus,DocumentType,UserType,SecurityValidationType,CountryCode, and more countries,currencies,statesstatic content- Validation regexes
Deep imports
Import a single domain to keep bundles small:
import { UserProxy } from "web3-banking-system-sdk/user";
import { AuthProxy } from "web3-banking-system-sdk/auth";
import { BlockchainAPI } from "web3-banking-system-sdk/blockchain";
import { TransactionProxy } from "web3-banking-system-sdk/transaction";Available subpaths: /user, /auth, /account, /transaction, /blockchain,
/order, /organization, /limited, /program, /promotion, /helpers,
/constants, /enums, /structures, /regex.
Note: the
./contentand./utilssubpaths declared inpackage.jsondo not resolve — the build emitsdist/contents.jsanddist/utility.js. Import that content from the package root until the export map is corrected.
Development
npm install
npm run build # tsc --build → dist/
npm test # jest (ts-jest, tests/unit/**)Only dist/ is published (files: ["/dist"]). Pushing to main triggers
.github/workflows/publish.yaml, which builds
and runs npm publish; the automatic version bump is currently commented out,
so bump package.json manually before merging a release.
Codebase rule: type placement
Every type and interface lives under src/types/, in a directory mirroring
the source file that uses it — src/helper/geoHelper.ts →
src/types/helper/geoHelper.ts. Never declare a type or interface inline in a
non-types file. See CLAUDE.md.
Links
License
ISC © GGEZ1 Foundation DAO LLC
