mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 01:08:07 +00:00
Update StandX API documentation and configuration
- Revised `.env.example` to reflect new API token generation process, emphasizing the use of creation date and validity days for token expiry management. - Enhanced `auth.md` with detailed instructions for obtaining API tokens and signing transactions for both EVM and Solana wallets. - Updated `maker-points-guide.md` to clarify the API token retrieval process and the significance of the Ed25519 private key. - Refactored `config.ts` and `gateway.ts` to support new token expiry configuration methods and improved private key handling, including Base58 decoding. - Improved overall documentation clarity and user guidance for new and existing users.
This commit is contained in:
+35
-10
@@ -10,22 +10,47 @@ export interface StandxTokenConfig {
|
||||
expiryTimestamp: number | null;
|
||||
}
|
||||
|
||||
function parseTimestamp(value: string | undefined): number | null {
|
||||
if (!value || !value.trim()) return null;
|
||||
const trimmed = value.trim();
|
||||
const asNumber = Number(trimmed);
|
||||
if (Number.isFinite(asNumber) && asNumber > 0) {
|
||||
return asNumber < 1e12 ? asNumber * 1000 : asNumber;
|
||||
function parseTokenExpiry(): number | null {
|
||||
// Method 1: Use creation date + validity days (recommended for official API tokens)
|
||||
const createDate = process.env.STANDX_TOKEN_CREATE_DATE?.trim();
|
||||
const validityDays = process.env.STANDX_TOKEN_VALIDITY_DAYS?.trim();
|
||||
|
||||
if (createDate && validityDays) {
|
||||
// Parse date in YYYY-MM-DD format
|
||||
const dateMatch = createDate.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (dateMatch) {
|
||||
const [, year, month, day] = dateMatch;
|
||||
const createTimestamp = Date.UTC(
|
||||
Number(year),
|
||||
Number(month) - 1, // Month is 0-indexed
|
||||
Number(day),
|
||||
0, 0, 0, 0
|
||||
);
|
||||
const days = Number(validityDays);
|
||||
if (Number.isFinite(createTimestamp) && Number.isFinite(days) && days > 0) {
|
||||
return createTimestamp + days * 24 * 60 * 60 * 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
const asDate = Date.parse(trimmed);
|
||||
if (Number.isFinite(asDate) && asDate > 0) {
|
||||
return asDate;
|
||||
|
||||
// Method 2: Use legacy STANDX_TOKEN_EXPIRY (timestamp or ISO date string)
|
||||
const legacyExpiry = process.env.STANDX_TOKEN_EXPIRY?.trim();
|
||||
if (legacyExpiry) {
|
||||
const asNumber = Number(legacyExpiry);
|
||||
if (Number.isFinite(asNumber) && asNumber > 0) {
|
||||
return asNumber < 1e12 ? asNumber * 1000 : asNumber;
|
||||
}
|
||||
const asDate = Date.parse(legacyExpiry);
|
||||
if (Number.isFinite(asDate) && asDate > 0) {
|
||||
return asDate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export const standxTokenConfig: StandxTokenConfig = {
|
||||
expiryTimestamp: parseTimestamp(process.env.STANDX_TOKEN_EXPIRY),
|
||||
expiryTimestamp: parseTokenExpiry(),
|
||||
};
|
||||
|
||||
export function isStandxTokenExpired(): boolean {
|
||||
|
||||
@@ -107,21 +107,66 @@ class StandxRequestSigner {
|
||||
}
|
||||
}
|
||||
|
||||
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
function decodeBase58(input: string): Uint8Array | null {
|
||||
try {
|
||||
const bytes: number[] = [];
|
||||
for (const char of input) {
|
||||
const value = BASE58_ALPHABET.indexOf(char);
|
||||
if (value === -1) return null;
|
||||
let carry = value;
|
||||
for (let i = 0; i < bytes.length; i += 1) {
|
||||
const current = bytes[i] ?? 0;
|
||||
carry += current * 58;
|
||||
bytes[i] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
while (carry > 0) {
|
||||
bytes.push(carry & 0xff);
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
// Handle leading zeros
|
||||
for (const char of input) {
|
||||
if (char !== "1") break;
|
||||
bytes.push(0);
|
||||
}
|
||||
return Uint8Array.from(bytes.reverse());
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function parseSigningKey(value?: string): Uint8Array | null {
|
||||
if (!value) return null;
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return null;
|
||||
// 0x-prefixed hex
|
||||
if (/^0x[0-9a-fA-F]+$/.test(trimmed)) {
|
||||
return Uint8Array.from(Buffer.from(trimmed.slice(2), "hex"));
|
||||
}
|
||||
// Pure hex (64 chars = 32 bytes for ed25519 private key)
|
||||
if (/^[0-9a-fA-F]+$/.test(trimmed)) {
|
||||
return Uint8Array.from(Buffer.from(trimmed, "hex"));
|
||||
}
|
||||
try {
|
||||
return Uint8Array.from(Buffer.from(trimmed, "base64"));
|
||||
} catch {
|
||||
return null;
|
||||
// Base58 (official StandX API format)
|
||||
if (/^[1-9A-HJ-NP-Za-km-z]+$/.test(trimmed)) {
|
||||
const decoded = decodeBase58(trimmed);
|
||||
if (decoded && decoded.length === 32) {
|
||||
return decoded;
|
||||
}
|
||||
}
|
||||
// Base64 fallback
|
||||
try {
|
||||
const decoded = Uint8Array.from(Buffer.from(trimmed, "base64"));
|
||||
if (decoded.length === 32) {
|
||||
return decoded;
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function normalizeSymbol(raw: string): string {
|
||||
|
||||
Reference in New Issue
Block a user