client-aftermath-ts-sdk
Version:
Client Aftermath TypeScript SDK
159 lines (158 loc) • 7.92 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Auth = void 0;
const caller_1 = require("../../general/utils/caller");
const utils_1 = require("../../general/utils");
class Auth extends caller_1.Caller {
// =========================================================================
// Constructor
// =========================================================================
constructor(config) {
super(config, "auth");
// =========================================================================
// Private Class Members
// =========================================================================
this.refreshTimer = null;
this.isCanceled = false;
}
// =========================================================================
// User-Facing
// =========================================================================
init(inputs) {
return __awaiter(this, void 0, void 0, function* () {
// Step 1: Mark as "not canceled" before the new run
this.isCanceled = false;
// Step 2: Define a function that does the “work” + schedules next call
const startRefresh = () => __awaiter(this, void 0, void 0, function* () {
// If canceled at the time we enter, don’t do anything
if (this.isCanceled)
return;
const { accessToken, expirationTimestamp } = yield this.getAccessToken(inputs);
this.setAccessToken(accessToken);
if (this.isCanceled)
return; // double-check before scheduling next timer
const TIMEOUT_REDUCTION_RATIO = 0.9;
const interval = (expirationTimestamp - Date.now()) * TIMEOUT_REDUCTION_RATIO;
// Store the timer so we can cancel it later
this.refreshTimer = setTimeout(startRefresh, interval);
});
// Step 3: Kick off the first refresh
yield startRefresh();
// Step 4: Return a function that cancels further refreshes
return () => {
this.isCanceled = true;
if (this.refreshTimer) {
clearTimeout(this.refreshTimer);
}
};
});
}
initFromSuiKeystore(inputs) {
return __awaiter(this, void 0, void 0, function* () {
const { walletAddress, path: pathStr } = inputs;
if (typeof window === "undefined") {
const fs = require("fs");
const path = require("path");
const os = require("os");
const keystorePath = pathStr
? path.join(pathStr)
: (() => {
// Locate the user’s home directory
const homeDir = os.homedir();
if (!homeDir) {
throw new Error("cannot obtain home directory path");
}
// Construct the path: ~/.sui/sui_config/sui.keystore
return path.join(homeDir, ".sui", "sui_config", "sui.keystore");
})();
// Read the JSON file from `keystorePath`
let privateKeys;
try {
const fileContent = fs.readFileSync(keystorePath, "utf-8");
privateKeys = JSON.parse(fileContent);
if (!Array.isArray(privateKeys)) {
throw new Error("Invalid keystore format: Expected an array of private keys");
}
}
catch (error) {
throw new Error(`Failed to read keystore file: ${error}`);
}
if (privateKeys.length <= 0) {
throw new Error(`Empty keystore file`);
}
const foundKeypair = privateKeys
.map((privateKey) => utils_1.Helpers.keypairFromPrivateKey(privateKey))
.find((keypair) => utils_1.Helpers.addLeadingZeroesToType(keypair.toSuiAddress()) === utils_1.Helpers.addLeadingZeroesToType(walletAddress));
if (!foundKeypair) {
throw new Error(`No private key found in keystore file for ${walletAddress}`);
}
return this.init({
walletAddress,
signMessageCallback: ({ message }) => __awaiter(this, void 0, void 0, function* () { return foundKeypair.signPersonalMessage(message); }),
});
}
throw new Error("`initFromSuiKeystore` must be called on server-side");
});
}
// =========================================================================
// Admin
// =========================================================================
// NOTE: admin only (should add docs)
adminCreateAuthAccount(inputs) {
return __awaiter(this, void 0, void 0, function* () {
const { walletAddress, signMessageCallback, accountName, accountWalletAddress, rateLimits, } = inputs;
const serializedJson = Auth.createSerializedJson("AccountCreate", {
sub: accountName,
wallet_address: utils_1.Helpers.addLeadingZeroesToType(accountWalletAddress),
rate_limits: rateLimits,
});
const message = new TextEncoder().encode(serializedJson);
const { signature } = yield signMessageCallback({ message });
return this.fetchApi("create-account", {
signature,
serializedJson,
walletAddress: utils_1.Helpers.addLeadingZeroesToType(walletAddress),
});
});
}
// =========================================================================
// Private
// =========================================================================
getAccessToken(inputs) {
return __awaiter(this, void 0, void 0, function* () {
const { walletAddress, signMessageCallback } = inputs;
const serializedJson = Auth.createSerializedJson("GetAccessToken", {});
const message = new TextEncoder().encode(serializedJson);
const { signature } = yield signMessageCallback({ message });
return this.fetchApi("access-token", {
signature,
serializedJson,
walletAddress: utils_1.Helpers.addLeadingZeroesToType(walletAddress),
});
});
}
// =========================================================================
// Private Static
// =========================================================================
static createSerializedJson(method, value) {
const timestampSeconds = Math.floor(Date.now() / 1000);
const random = Math.floor(Math.random() * 1024 * 1024);
const data = {
date: timestampSeconds,
nonce: random,
method: method,
value: value,
};
return JSON.stringify(data);
}
}
exports.Auth = Auth;