@pollar/core 0.4.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1497 -326
- package/dist/index.d.ts +1497 -326
- package/dist/index.js +314 -191
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +305 -189
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -652,31 +652,98 @@ function createApiClient(baseUrl) {
|
|
|
652
652
|
return createClient({ baseUrl });
|
|
653
653
|
}
|
|
654
654
|
|
|
655
|
-
// src/
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
655
|
+
// src/api/endpoints/kyc.ts
|
|
656
|
+
async function getKycStatus(api, providerId) {
|
|
657
|
+
const { data, error } = await api.GET("/kyc/status", {
|
|
658
|
+
params: { query: providerId ? { providerId } : {} }
|
|
659
|
+
});
|
|
660
|
+
if (!data?.content || error) {
|
|
661
|
+
throw new Error(error?.error ?? "Failed to get KYC status");
|
|
662
|
+
}
|
|
663
|
+
return data.content;
|
|
664
|
+
}
|
|
665
|
+
async function getKycProviders(api, country) {
|
|
666
|
+
const { data, error } = await api.GET("/kyc/providers", { params: { query: { country } } });
|
|
667
|
+
if (!data?.content || error) throw new Error(error?.error ?? "Failed to get KYC providers");
|
|
668
|
+
return data.content;
|
|
669
|
+
}
|
|
670
|
+
async function startKyc(api, body) {
|
|
671
|
+
const { data, error } = await api.POST("/kyc/start", { body });
|
|
672
|
+
if (!data?.content || error) throw new Error(error?.error ?? "Failed to start KYC");
|
|
673
|
+
return data.content;
|
|
674
|
+
}
|
|
675
|
+
async function resolveKyc(api, providerId, level = "basic") {
|
|
676
|
+
const { status } = await getKycStatus(api, providerId);
|
|
677
|
+
if (status === "approved") return { alreadyApproved: true };
|
|
678
|
+
const started = await startKyc(api, { providerId, level });
|
|
679
|
+
return { alreadyApproved: false, ...started };
|
|
680
|
+
}
|
|
681
|
+
async function pollKycStatus(api, providerId, { intervalMs = 3e3, timeoutMs = 3e5 } = {}) {
|
|
682
|
+
const deadline = Date.now() + timeoutMs;
|
|
683
|
+
while (Date.now() < deadline) {
|
|
684
|
+
const { status } = await getKycStatus(api, providerId);
|
|
685
|
+
if (status === "approved" || status === "rejected") return status;
|
|
686
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
687
|
+
}
|
|
688
|
+
throw new Error("KYC polling timed out");
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/api/endpoints/ramps.ts
|
|
692
|
+
async function getRampsQuote(api, query) {
|
|
693
|
+
const { data, error } = await api.GET("/ramps/quote", { params: { query } });
|
|
694
|
+
if (!data?.content || error) throw new Error(error?.error ?? "Failed to get ramp quotes");
|
|
695
|
+
return data.content;
|
|
696
|
+
}
|
|
697
|
+
async function createOnRamp(api, body) {
|
|
698
|
+
const { data, error } = await api.POST("/ramps/onramp", { body });
|
|
699
|
+
if (!data?.content || error) throw new Error(error?.error ?? "Failed to create onramp");
|
|
700
|
+
return data.content;
|
|
701
|
+
}
|
|
702
|
+
async function createOffRamp(api, body) {
|
|
703
|
+
const { data, error } = await api.POST("/ramps/offramp", { body });
|
|
704
|
+
if (!data?.content || error) throw new Error(error?.error ?? "Failed to create offramp");
|
|
705
|
+
return data.content;
|
|
706
|
+
}
|
|
707
|
+
async function getRampTransaction(api, txId) {
|
|
708
|
+
const { data, error } = await api.GET("/ramps/transaction/{txId}", { params: { path: { txId } } });
|
|
709
|
+
if (!data?.content || error) throw new Error(error?.error ?? "Failed to get transaction");
|
|
710
|
+
return data.content;
|
|
711
|
+
}
|
|
712
|
+
async function pollRampTransaction(api, txId, { intervalMs = 5e3, timeoutMs = 6e5 } = {}) {
|
|
713
|
+
const deadline = Date.now() + timeoutMs;
|
|
714
|
+
while (Date.now() < deadline) {
|
|
715
|
+
const { status } = await getRampTransaction(api, txId);
|
|
716
|
+
if (status === "completed" || status === "failed") return status;
|
|
717
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
718
|
+
}
|
|
719
|
+
throw new Error("Ramp transaction polling timed out");
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// src/stellar/StellarClient.ts
|
|
723
|
+
var HORIZON_URLS = {
|
|
724
|
+
mainnet: "https://horizon.stellar.org",
|
|
725
|
+
testnet: "https://horizon-testnet.stellar.org"
|
|
665
726
|
};
|
|
666
|
-
var
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
727
|
+
var StellarClient = class {
|
|
728
|
+
constructor(config) {
|
|
729
|
+
this.horizonUrl = typeof config === "string" ? HORIZON_URLS[config] : config.horizonUrl;
|
|
730
|
+
}
|
|
731
|
+
async submitTransaction(signedXdr) {
|
|
732
|
+
try {
|
|
733
|
+
const response = await fetch(`${this.horizonUrl}/transactions`, {
|
|
734
|
+
method: "POST",
|
|
735
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
736
|
+
body: new URLSearchParams({ tx: signedXdr })
|
|
737
|
+
});
|
|
738
|
+
if (!response.ok) {
|
|
739
|
+
const body = await response.json().catch(() => ({}));
|
|
740
|
+
return { success: false, errorCode: body.extras?.result_codes?.transaction ?? "HORIZON_ERROR" };
|
|
741
|
+
}
|
|
742
|
+
const data = await response.json();
|
|
743
|
+
return { success: true, hash: data.hash };
|
|
744
|
+
} catch {
|
|
745
|
+
return { success: false, errorCode: "NETWORK_ERROR" };
|
|
746
|
+
}
|
|
680
747
|
}
|
|
681
748
|
};
|
|
682
749
|
|
|
@@ -933,8 +1000,8 @@ async function authenticate(clientSessionId, deps) {
|
|
|
933
1000
|
}
|
|
934
1001
|
}
|
|
935
1002
|
|
|
936
|
-
// src/client/auth/
|
|
937
|
-
async function
|
|
1003
|
+
// src/client/auth/deps.ts
|
|
1004
|
+
async function createAuthSession(deps) {
|
|
938
1005
|
const { api, signal, setAuthState } = deps;
|
|
939
1006
|
setAuthState({ step: "creating_session" });
|
|
940
1007
|
const { data, error } = await api.POST("/auth/session", { signal });
|
|
@@ -945,9 +1012,16 @@ async function initEmailSession(deps) {
|
|
|
945
1012
|
message: "Failed to create session",
|
|
946
1013
|
errorCode: AUTH_ERROR_CODES.SESSION_CREATE_FAILED
|
|
947
1014
|
});
|
|
948
|
-
return;
|
|
1015
|
+
return null;
|
|
949
1016
|
}
|
|
950
|
-
|
|
1017
|
+
return data.content.clientSessionId;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// src/client/auth/emailFlow.ts
|
|
1021
|
+
async function initEmailSession(deps) {
|
|
1022
|
+
const clientSessionId = await createAuthSession(deps);
|
|
1023
|
+
if (!clientSessionId) return;
|
|
1024
|
+
deps.setAuthState({ step: "entering_email", clientSessionId });
|
|
951
1025
|
}
|
|
952
1026
|
async function sendEmailCode(email, clientSessionId, deps) {
|
|
953
1027
|
const { api, signal, setAuthState } = deps;
|
|
@@ -1010,25 +1084,10 @@ async function verifyAndAuthenticate(code, clientSessionId, email, deps) {
|
|
|
1010
1084
|
}
|
|
1011
1085
|
|
|
1012
1086
|
// src/client/auth/oauthFlow.ts
|
|
1013
|
-
async function initOAuthSession(deps) {
|
|
1014
|
-
const { api, signal, setAuthState } = deps;
|
|
1015
|
-
setAuthState({ step: "creating_session" });
|
|
1016
|
-
const { data, error } = await api.POST("/auth/session", { signal });
|
|
1017
|
-
if (error || !data?.success) {
|
|
1018
|
-
setAuthState({
|
|
1019
|
-
step: "error",
|
|
1020
|
-
previousStep: "creating_session",
|
|
1021
|
-
message: "Failed to create session",
|
|
1022
|
-
errorCode: AUTH_ERROR_CODES.SESSION_CREATE_FAILED
|
|
1023
|
-
});
|
|
1024
|
-
return null;
|
|
1025
|
-
}
|
|
1026
|
-
return data.content.clientSessionId;
|
|
1027
|
-
}
|
|
1028
1087
|
async function loginOAuth(provider, deps) {
|
|
1029
1088
|
const { setAuthState, basePath, apiKey } = deps;
|
|
1030
1089
|
const popup = window.open("about:blank", "_blank");
|
|
1031
|
-
const clientSessionId = await
|
|
1090
|
+
const clientSessionId = await createAuthSession(deps);
|
|
1032
1091
|
if (!clientSessionId) {
|
|
1033
1092
|
popup?.close();
|
|
1034
1093
|
return;
|
|
@@ -1228,18 +1287,8 @@ function withSignal(promise, signal) {
|
|
|
1228
1287
|
}
|
|
1229
1288
|
async function loginWallet(type, deps) {
|
|
1230
1289
|
const { api, signal, setAuthState } = deps;
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
if (error || !data?.success) {
|
|
1234
|
-
setAuthState({
|
|
1235
|
-
step: "error",
|
|
1236
|
-
previousStep: "creating_session",
|
|
1237
|
-
message: "Failed to create session",
|
|
1238
|
-
errorCode: AUTH_ERROR_CODES.SESSION_CREATE_FAILED
|
|
1239
|
-
});
|
|
1240
|
-
return;
|
|
1241
|
-
}
|
|
1242
|
-
const clientSessionId = data.content.clientSessionId;
|
|
1290
|
+
const clientSessionId = await createAuthSession(deps);
|
|
1291
|
+
if (!clientSessionId) return;
|
|
1243
1292
|
try {
|
|
1244
1293
|
setAuthState({ step: "connecting_wallet", walletType: type });
|
|
1245
1294
|
const adapter = type === "freighter" /* FREIGHTER */ ? new FreighterAdapter() : new AlbedoAdapter();
|
|
@@ -1249,6 +1298,7 @@ async function loginWallet(type, deps) {
|
|
|
1249
1298
|
return;
|
|
1250
1299
|
}
|
|
1251
1300
|
const { publicKey } = await withSignal(adapter.connect(), signal);
|
|
1301
|
+
deps.storeWalletAdapter(adapter);
|
|
1252
1302
|
setAuthState({ step: "authenticating_wallet" });
|
|
1253
1303
|
const { data: walletData, error: walletError } = await api.POST("/auth/wallet", {
|
|
1254
1304
|
body: { clientSessionId, walletAddress: publicKey },
|
|
@@ -1275,19 +1325,6 @@ async function loginWallet(type, deps) {
|
|
|
1275
1325
|
await authenticate(clientSessionId, deps);
|
|
1276
1326
|
}
|
|
1277
1327
|
|
|
1278
|
-
// src/client/helpers.ts
|
|
1279
|
-
var emitResponse = (state, response, success, errorCode, emitLog) => {
|
|
1280
|
-
const isSuccess = !response.error && !!response.data && !!response.data?.success;
|
|
1281
|
-
emitLog(
|
|
1282
|
-
state,
|
|
1283
|
-
isSuccess ? success.code : errorCode,
|
|
1284
|
-
isSuccess ? "info" : "error",
|
|
1285
|
-
isSuccess ? success.status || StateStatus.LOADING : StateStatus.ERROR,
|
|
1286
|
-
isSuccess ? response.data : response.error
|
|
1287
|
-
);
|
|
1288
|
-
return isSuccess;
|
|
1289
|
-
};
|
|
1290
|
-
|
|
1291
1328
|
// src/client/client.ts
|
|
1292
1329
|
var isBrowser = typeof window !== "undefined" && typeof localStorage !== "undefined";
|
|
1293
1330
|
function warnServerSide(method) {
|
|
@@ -1298,46 +1335,48 @@ function warnServerSide(method) {
|
|
|
1298
1335
|
var PollarClient = class {
|
|
1299
1336
|
constructor(config) {
|
|
1300
1337
|
this._session = null;
|
|
1301
|
-
this.
|
|
1302
|
-
this.
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
};
|
|
1338
|
+
this._transactionState = null;
|
|
1339
|
+
this._transactionStateListeners = /* @__PURE__ */ new Set();
|
|
1340
|
+
this._txHistoryState = { step: "idle" };
|
|
1341
|
+
this._txHistoryStateListeners = /* @__PURE__ */ new Set();
|
|
1306
1342
|
this._authState = { step: "idle" };
|
|
1307
1343
|
this._authStateListeners = /* @__PURE__ */ new Set();
|
|
1344
|
+
this._networkState = { step: "idle" };
|
|
1345
|
+
this._networkStateListeners = /* @__PURE__ */ new Set();
|
|
1346
|
+
this._walletAdapter = null;
|
|
1308
1347
|
this._loginController = null;
|
|
1309
1348
|
this.apiKey = config.apiKey;
|
|
1310
1349
|
this.id = crypto.randomUUID();
|
|
1311
1350
|
this.basePath = `${config.baseUrl || "https://sdk.api.pollar.xyz"}/v1`;
|
|
1312
1351
|
this._api = createApiClient(this.basePath);
|
|
1352
|
+
const self = this;
|
|
1313
1353
|
this._api.use({
|
|
1314
1354
|
onRequest({ request }) {
|
|
1315
1355
|
request.headers.set("x-pollar-api-key", config.apiKey);
|
|
1356
|
+
const accessToken = self._session?.token?.accessToken;
|
|
1357
|
+
if (accessToken) {
|
|
1358
|
+
request.headers.set("Authorization", `Bearer ${accessToken}`);
|
|
1359
|
+
}
|
|
1316
1360
|
return request;
|
|
1317
1361
|
}
|
|
1318
1362
|
});
|
|
1363
|
+
this._networkState = { step: "connected", network: config.stellarNetwork ?? "testnet" };
|
|
1319
1364
|
if (!isBrowser) {
|
|
1320
1365
|
warnServerSide("constructor");
|
|
1321
1366
|
this._session = null;
|
|
1322
1367
|
return;
|
|
1323
1368
|
}
|
|
1324
|
-
console.info(`[PollarClient] Initialized \u2014 endpoint: ${this.basePath}`);
|
|
1325
|
-
this.
|
|
1369
|
+
console.info(`[PollarClient] Initialized \u2014 endpoint: ${this.basePath}, network: ${this._networkState.network}`);
|
|
1370
|
+
this._restoreSession();
|
|
1326
1371
|
window.addEventListener("storage", (e) => {
|
|
1327
1372
|
if (e.key === STORAGE_KEY) {
|
|
1328
1373
|
const prev = this._session;
|
|
1329
1374
|
console.info(`[PollarClient] Storage event \u2014 session ${this._session ? "updated" : prev ? "cleared" : "unchanged"}`);
|
|
1330
|
-
this.
|
|
1375
|
+
this._restoreSession();
|
|
1331
1376
|
}
|
|
1332
1377
|
});
|
|
1333
|
-
this._emitState("network", STATE_VAR_CODES.network.NETWORK_UPDATED, "info", StateStatus.SUCCESS, {
|
|
1334
|
-
network: "testnet"
|
|
1335
|
-
});
|
|
1336
1378
|
}
|
|
1337
1379
|
// ─── Auth state ──────────────────────────────────────────────────────────────
|
|
1338
|
-
isAuthenticated() {
|
|
1339
|
-
return !!this._session?.wallet?.publicKey;
|
|
1340
|
-
}
|
|
1341
1380
|
getAuthState() {
|
|
1342
1381
|
return this._authState;
|
|
1343
1382
|
}
|
|
@@ -1352,17 +1391,23 @@ var PollarClient = class {
|
|
|
1352
1391
|
warnServerSide("login");
|
|
1353
1392
|
return;
|
|
1354
1393
|
}
|
|
1355
|
-
if (options.provider === "google" || options.provider === "github") {
|
|
1356
|
-
this.loginOAuth(options.provider);
|
|
1357
|
-
} else if (options.provider === "email") {
|
|
1358
|
-
const { email } = options;
|
|
1394
|
+
if (options.provider === "google" || options.provider === "github" || options.provider === "email") {
|
|
1359
1395
|
const controller = this._newController();
|
|
1360
1396
|
const deps = this._flowDeps(controller.signal);
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1397
|
+
if (options.provider === "google" || options.provider === "github") {
|
|
1398
|
+
loginOAuth(options.provider, {
|
|
1399
|
+
...deps,
|
|
1400
|
+
basePath: this.basePath,
|
|
1401
|
+
apiKey: this.apiKey
|
|
1402
|
+
}).catch((err) => this._handleFlowError(err));
|
|
1403
|
+
} else if (options.provider === "email") {
|
|
1404
|
+
const { email } = options;
|
|
1405
|
+
initEmailSession(deps).then(() => {
|
|
1406
|
+
if (this._authState.step === "entering_email") {
|
|
1407
|
+
return sendEmailCode(email, this._authState.clientSessionId, deps);
|
|
1408
|
+
}
|
|
1409
|
+
}).catch((err) => this._handleFlowError(err));
|
|
1410
|
+
}
|
|
1366
1411
|
} else if (options.provider === "wallet") {
|
|
1367
1412
|
this.loginWallet(options.type);
|
|
1368
1413
|
}
|
|
@@ -1405,19 +1450,6 @@ var PollarClient = class {
|
|
|
1405
1450
|
(err) => this._handleFlowError(err)
|
|
1406
1451
|
);
|
|
1407
1452
|
}
|
|
1408
|
-
// ─── OAuth flow (single call) ─────────────────────────────────────────────
|
|
1409
|
-
loginOAuth(provider) {
|
|
1410
|
-
if (!isBrowser) {
|
|
1411
|
-
warnServerSide("loginOAuth");
|
|
1412
|
-
return;
|
|
1413
|
-
}
|
|
1414
|
-
const controller = this._newController();
|
|
1415
|
-
loginOAuth(provider, {
|
|
1416
|
-
...this._flowDeps(controller.signal),
|
|
1417
|
-
basePath: this.basePath,
|
|
1418
|
-
apiKey: this.apiKey
|
|
1419
|
-
}).catch((err) => this._handleFlowError(err));
|
|
1420
|
-
}
|
|
1421
1453
|
// ─── Wallet flow (single call) ────────────────────────────────────────────
|
|
1422
1454
|
loginWallet(type) {
|
|
1423
1455
|
if (!isBrowser) {
|
|
@@ -1442,24 +1474,70 @@ var PollarClient = class {
|
|
|
1442
1474
|
console.info("[PollarClient] Logout requested");
|
|
1443
1475
|
this._clearSession();
|
|
1444
1476
|
}
|
|
1445
|
-
// ───
|
|
1446
|
-
getApi() {
|
|
1447
|
-
return this._api;
|
|
1448
|
-
}
|
|
1477
|
+
// ─── Network ──────────────────────────────────────────────────────────────
|
|
1449
1478
|
getNetwork() {
|
|
1450
|
-
return this.
|
|
1479
|
+
return this._networkState.step === "connected" ? this._networkState.network : "testnet";
|
|
1480
|
+
}
|
|
1481
|
+
getNetworkState() {
|
|
1482
|
+
return this._networkState;
|
|
1483
|
+
}
|
|
1484
|
+
setNetwork(network) {
|
|
1485
|
+
this._setNetworkState({ step: "connected", network });
|
|
1486
|
+
}
|
|
1487
|
+
onNetworkStateChange(cb) {
|
|
1488
|
+
this._networkStateListeners.add(cb);
|
|
1489
|
+
cb(this._networkState);
|
|
1490
|
+
return () => this._networkStateListeners.delete(cb);
|
|
1451
1491
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1492
|
+
// ─── Transaction state ────────────────────────────────────────────────────
|
|
1493
|
+
getTransactionState() {
|
|
1494
|
+
return this._transactionState;
|
|
1495
|
+
}
|
|
1496
|
+
onTransactionStateChange(cb) {
|
|
1497
|
+
this._transactionStateListeners.add(cb);
|
|
1498
|
+
if (this._transactionState) cb(this._transactionState);
|
|
1499
|
+
return () => this._transactionStateListeners.delete(cb);
|
|
1500
|
+
}
|
|
1501
|
+
// ─── Tx history ──────────────────────────────────────────────────────────
|
|
1502
|
+
_setTxHistoryState(next) {
|
|
1503
|
+
this._txHistoryState = next;
|
|
1504
|
+
for (const cb of this._txHistoryStateListeners) cb(next);
|
|
1505
|
+
}
|
|
1506
|
+
getTxHistoryState() {
|
|
1507
|
+
return this._txHistoryState;
|
|
1508
|
+
}
|
|
1509
|
+
onTxHistoryStateChange(cb) {
|
|
1510
|
+
this._txHistoryStateListeners.add(cb);
|
|
1511
|
+
cb(this._txHistoryState);
|
|
1512
|
+
return () => this._txHistoryStateListeners.delete(cb);
|
|
1513
|
+
}
|
|
1514
|
+
async fetchTxHistory(params = {}) {
|
|
1515
|
+
this._setTxHistoryState({ step: "loading", params });
|
|
1516
|
+
try {
|
|
1517
|
+
const { data, error } = await this._api.GET("/tx/history", { params: { query: params } });
|
|
1518
|
+
if (!error && data?.success && data.content) {
|
|
1519
|
+
this._setTxHistoryState({ step: "loaded", params, data: data.content });
|
|
1520
|
+
} else {
|
|
1521
|
+
const message = error?.message ?? "Failed to load history";
|
|
1522
|
+
this._setTxHistoryState({ step: "error", params, message });
|
|
1523
|
+
}
|
|
1524
|
+
} catch {
|
|
1525
|
+
this._setTxHistoryState({ step: "error", params, message: "Failed to load history" });
|
|
1456
1526
|
}
|
|
1457
|
-
|
|
1527
|
+
}
|
|
1528
|
+
// ─── Wallet balance ───────────────────────────────────────────────────────
|
|
1529
|
+
async getWalletBalance(publicKey) {
|
|
1530
|
+
const pk = publicKey ?? this._session?.wallet?.publicKey;
|
|
1531
|
+
if (!pk) return null;
|
|
1532
|
+
const network = this.getNetwork();
|
|
1533
|
+
const { data, error } = await this._api.GET("/wallet/balance", { params: { query: { publicKey: pk, network } } });
|
|
1534
|
+
if (!error && data?.success && data.content) return data.content;
|
|
1535
|
+
return null;
|
|
1458
1536
|
}
|
|
1459
1537
|
// ─── Transactions ─────────────────────────────────────────────────────────
|
|
1460
1538
|
async buildTx(operation, params, options) {
|
|
1461
1539
|
if (!this._session?.wallet?.publicKey) {
|
|
1462
|
-
this.
|
|
1540
|
+
this._setTransactionState({ step: "error", details: "No wallet connected" });
|
|
1463
1541
|
return;
|
|
1464
1542
|
}
|
|
1465
1543
|
const body = {
|
|
@@ -1467,42 +1545,104 @@ var PollarClient = class {
|
|
|
1467
1545
|
publicKey: this._session.wallet.publicKey,
|
|
1468
1546
|
operation,
|
|
1469
1547
|
params,
|
|
1470
|
-
options: options
|
|
1548
|
+
options: options ?? {}
|
|
1471
1549
|
};
|
|
1472
1550
|
try {
|
|
1473
|
-
this.
|
|
1474
|
-
const
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1551
|
+
this._setTransactionState({ step: "building" });
|
|
1552
|
+
const { data, error } = await this._api.POST("/tx/build", { body });
|
|
1553
|
+
if (!error && data?.success && data.content) {
|
|
1554
|
+
this._setTransactionState({ step: "built", buildData: data.content });
|
|
1555
|
+
} else {
|
|
1556
|
+
const details = error?.details;
|
|
1557
|
+
this._setTransactionState({ step: "error", ...details && { details } });
|
|
1558
|
+
}
|
|
1559
|
+
} catch {
|
|
1560
|
+
this._setTransactionState({ step: "error" });
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
async signAndSubmitTx(unsignedXdr) {
|
|
1564
|
+
if (this._transactionState?.step !== "built") {
|
|
1565
|
+
throw new PollarFlowError(
|
|
1566
|
+
`signAndSubmitTx() requires step 'built', current step is '${this._transactionState?.step ?? "none"}'`
|
|
1481
1567
|
);
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1568
|
+
}
|
|
1569
|
+
const buildData = this._transactionState.buildData;
|
|
1570
|
+
this._setTransactionState({ step: "signing", buildData });
|
|
1571
|
+
if (this._walletAdapter) {
|
|
1572
|
+
try {
|
|
1573
|
+
const signOpts = this._session?.wallet?.publicKey ? { networkPassphrase: this._networkPassphrase(), accountToSign: this._session.wallet.publicKey } : { networkPassphrase: this._networkPassphrase() };
|
|
1574
|
+
const { signedTxXdr } = await this._walletAdapter.signTransaction(unsignedXdr, signOpts);
|
|
1575
|
+
const stellarClient = new StellarClient(this.getNetwork());
|
|
1576
|
+
const result = await stellarClient.submitTransaction(signedTxXdr);
|
|
1577
|
+
if (result.success) {
|
|
1578
|
+
this._setTransactionState({ step: "success", buildData, hash: result.hash });
|
|
1579
|
+
} else {
|
|
1580
|
+
this._setTransactionState({ step: "error", ...buildData && { buildData }, details: result.errorCode });
|
|
1581
|
+
}
|
|
1582
|
+
} catch {
|
|
1583
|
+
this._setTransactionState({ step: "error", ...buildData && { buildData } });
|
|
1584
|
+
}
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
const body = {
|
|
1588
|
+
network: this.getNetwork(),
|
|
1589
|
+
publicKey: this._session?.wallet?.publicKey ?? "",
|
|
1590
|
+
unsignedXdr
|
|
1591
|
+
};
|
|
1592
|
+
try {
|
|
1593
|
+
const { data, error } = await this._api.POST("/tx/sign-and-send", { body });
|
|
1594
|
+
if (!error && data?.success && data.content?.hash) {
|
|
1595
|
+
this._setTransactionState({ step: "success", buildData, hash: data.content.hash });
|
|
1596
|
+
} else {
|
|
1597
|
+
const details = error?.details;
|
|
1598
|
+
this._setTransactionState({ step: "error", ...buildData && { buildData }, ...details && { details } });
|
|
1599
|
+
}
|
|
1600
|
+
} catch {
|
|
1601
|
+
this._setTransactionState({ step: "error", ...buildData && { buildData } });
|
|
1486
1602
|
}
|
|
1487
1603
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1604
|
+
// ─── App config ───────────────────────────────────────────────────────────
|
|
1605
|
+
async getAppConfig() {
|
|
1490
1606
|
try {
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
{ code: STATE_VAR_CODES.transaction.SIGN_SEND_TRANSACTION_SUCCESS, status: StateStatus.SUCCESS },
|
|
1497
|
-
STATE_VAR_CODES.transaction.SIGN_SEND_TRANSACTION_ERROR,
|
|
1498
|
-
this._emitState.bind(this)
|
|
1499
|
-
);
|
|
1500
|
-
} catch (error) {
|
|
1501
|
-
this._emitState("transaction", STATE_VAR_CODES.transaction.SIGN_SEND_TRANSACTION_ERROR, "error", StateStatus.ERROR, {
|
|
1502
|
-
error
|
|
1503
|
-
});
|
|
1607
|
+
const { data, error } = await this._api.GET("/applications/config");
|
|
1608
|
+
if (!data || error) return null;
|
|
1609
|
+
return data.content;
|
|
1610
|
+
} catch {
|
|
1611
|
+
return null;
|
|
1504
1612
|
}
|
|
1505
1613
|
}
|
|
1614
|
+
// ─── KYC ──────────────────────────────────────────────────────────────────
|
|
1615
|
+
getKycStatus(providerId) {
|
|
1616
|
+
return getKycStatus(this._api, providerId);
|
|
1617
|
+
}
|
|
1618
|
+
getKycProviders(country) {
|
|
1619
|
+
return getKycProviders(this._api, country);
|
|
1620
|
+
}
|
|
1621
|
+
startKyc(body) {
|
|
1622
|
+
return startKyc(this._api, body);
|
|
1623
|
+
}
|
|
1624
|
+
resolveKyc(providerId, level) {
|
|
1625
|
+
return resolveKyc(this._api, providerId, level);
|
|
1626
|
+
}
|
|
1627
|
+
pollKycStatus(providerId, opts) {
|
|
1628
|
+
return pollKycStatus(this._api, providerId, opts);
|
|
1629
|
+
}
|
|
1630
|
+
// ─── Ramps ────────────────────────────────────────────────────────────────
|
|
1631
|
+
getRampsQuote(query) {
|
|
1632
|
+
return getRampsQuote(this._api, query);
|
|
1633
|
+
}
|
|
1634
|
+
createOnRamp(body) {
|
|
1635
|
+
return createOnRamp(this._api, body);
|
|
1636
|
+
}
|
|
1637
|
+
createOffRamp(body) {
|
|
1638
|
+
return createOffRamp(this._api, body);
|
|
1639
|
+
}
|
|
1640
|
+
getRampTransaction(txId) {
|
|
1641
|
+
return getRampTransaction(this._api, txId);
|
|
1642
|
+
}
|
|
1643
|
+
pollRampTransaction(txId, opts) {
|
|
1644
|
+
return pollRampTransaction(this._api, txId, opts);
|
|
1645
|
+
}
|
|
1506
1646
|
// ─── Private ──────────────────────────────────────────────────────────────
|
|
1507
1647
|
/** Creates a new AbortController, cancelling any existing flow first. */
|
|
1508
1648
|
_newController() {
|
|
@@ -1517,7 +1657,10 @@ var PollarClient = class {
|
|
|
1517
1657
|
signal,
|
|
1518
1658
|
setAuthState: this._setAuthState.bind(this),
|
|
1519
1659
|
storeSession: this._storeSession.bind(this),
|
|
1520
|
-
clearSession: this._clearSession.bind(this)
|
|
1660
|
+
clearSession: this._clearSession.bind(this),
|
|
1661
|
+
storeWalletAdapter: (adapter) => {
|
|
1662
|
+
this._walletAdapter = adapter;
|
|
1663
|
+
}
|
|
1521
1664
|
};
|
|
1522
1665
|
}
|
|
1523
1666
|
_handleFlowError(error) {
|
|
@@ -1534,7 +1677,7 @@ var PollarClient = class {
|
|
|
1534
1677
|
errorCode: AUTH_ERROR_CODES.UNEXPECTED_ERROR
|
|
1535
1678
|
});
|
|
1536
1679
|
}
|
|
1537
|
-
|
|
1680
|
+
_restoreSession() {
|
|
1538
1681
|
this._session = readStorage();
|
|
1539
1682
|
if (this._session) {
|
|
1540
1683
|
this._authState = { step: "authenticated", session: this._session };
|
|
@@ -1552,56 +1695,29 @@ var PollarClient = class {
|
|
|
1552
1695
|
_clearSession() {
|
|
1553
1696
|
console.info("[PollarClient] Session cleared");
|
|
1554
1697
|
this._session = null;
|
|
1698
|
+
this._walletAdapter = null;
|
|
1555
1699
|
removeStorage();
|
|
1556
|
-
this.
|
|
1700
|
+
this._transactionState = null;
|
|
1557
1701
|
this._setAuthState({ step: "idle" });
|
|
1558
1702
|
}
|
|
1703
|
+
_networkPassphrase() {
|
|
1704
|
+
return this.getNetwork() === "mainnet" ? "Public Global Stellar Network ; September 2015" : "Test SDF Network ; September 2015";
|
|
1705
|
+
}
|
|
1706
|
+
_setNetworkState(next) {
|
|
1707
|
+
this._networkState = next;
|
|
1708
|
+
const label = next.step === "connected" ? next.network : next.step;
|
|
1709
|
+
console.info(`[PollarClient] network:${label}`);
|
|
1710
|
+
for (const cb of this._networkStateListeners) cb(next);
|
|
1711
|
+
}
|
|
1559
1712
|
_setAuthState(next) {
|
|
1560
1713
|
this._authState = next;
|
|
1561
1714
|
console.info(`[PollarClient] auth:${next.step}`);
|
|
1562
1715
|
for (const cb of this._authStateListeners) cb(next);
|
|
1563
1716
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
for (const cb of this._stateListeners) cb(stateEntry);
|
|
1569
|
-
}
|
|
1570
|
-
};
|
|
1571
|
-
|
|
1572
|
-
// src/stellar/StellarClient.ts
|
|
1573
|
-
var HORIZON_URLS = {
|
|
1574
|
-
mainnet: "https://horizon.stellar.org",
|
|
1575
|
-
testnet: "https://horizon-testnet.stellar.org"
|
|
1576
|
-
};
|
|
1577
|
-
var StellarClient = class {
|
|
1578
|
-
constructor(config) {
|
|
1579
|
-
this.horizonUrl = typeof config === "string" ? HORIZON_URLS[config] : config.horizonUrl;
|
|
1580
|
-
}
|
|
1581
|
-
async getBalances(publicKey) {
|
|
1582
|
-
try {
|
|
1583
|
-
const response = await fetch(`${this.horizonUrl}/accounts/${publicKey}`);
|
|
1584
|
-
if (!response.ok) {
|
|
1585
|
-
if (response.status === 404) {
|
|
1586
|
-
console.warn(`[StellarClient] Account not found: ${publicKey}`);
|
|
1587
|
-
return { success: false, errorCode: "ACCOUNT_NOT_FOUND", balances: [] };
|
|
1588
|
-
}
|
|
1589
|
-
console.warn(`[StellarClient] Horizon API error: ${response.status}`);
|
|
1590
|
-
return { success: false, errorCode: "HORIZON_ERROR", balances: [] };
|
|
1591
|
-
}
|
|
1592
|
-
const data = await response.json();
|
|
1593
|
-
return {
|
|
1594
|
-
success: true,
|
|
1595
|
-
balances: data.balances.filter((b) => b.asset_type !== "liquidity_pool_shares").map((b) => ({
|
|
1596
|
-
asset: b.asset_type === "native" ? "XLM" : b.asset_code ?? "",
|
|
1597
|
-
balance: b.balance,
|
|
1598
|
-
...b.asset_type !== "native" && { assetIssuer: b.asset_issuer }
|
|
1599
|
-
}))
|
|
1600
|
-
};
|
|
1601
|
-
} catch (error) {
|
|
1602
|
-
console.warn("[StellarClient] Network error fetching balances", error);
|
|
1603
|
-
return { success: false, errorCode: "NETWORK_ERROR", balances: [] };
|
|
1604
|
-
}
|
|
1717
|
+
_setTransactionState(next) {
|
|
1718
|
+
this._transactionState = next;
|
|
1719
|
+
console.info(`[PollarClient] transaction:${next.step}`);
|
|
1720
|
+
for (const cb of this._transactionStateListeners) cb(next);
|
|
1605
1721
|
}
|
|
1606
1722
|
};
|
|
1607
1723
|
|
|
@@ -1609,11 +1725,18 @@ exports.AUTH_ERROR_CODES = AUTH_ERROR_CODES;
|
|
|
1609
1725
|
exports.AlbedoAdapter = AlbedoAdapter;
|
|
1610
1726
|
exports.FreighterAdapter = FreighterAdapter;
|
|
1611
1727
|
exports.PollarClient = PollarClient;
|
|
1612
|
-
exports.PollarStateVar = PollarStateVar;
|
|
1613
|
-
exports.STATE_VAR_CODES = STATE_VAR_CODES;
|
|
1614
|
-
exports.StateStatus = StateStatus;
|
|
1615
1728
|
exports.StellarClient = StellarClient;
|
|
1616
1729
|
exports.WalletType = WalletType;
|
|
1730
|
+
exports.createOffRamp = createOffRamp;
|
|
1731
|
+
exports.createOnRamp = createOnRamp;
|
|
1732
|
+
exports.getKycProviders = getKycProviders;
|
|
1733
|
+
exports.getKycStatus = getKycStatus;
|
|
1734
|
+
exports.getRampTransaction = getRampTransaction;
|
|
1735
|
+
exports.getRampsQuote = getRampsQuote;
|
|
1617
1736
|
exports.isValidSession = isValidSession;
|
|
1737
|
+
exports.pollKycStatus = pollKycStatus;
|
|
1738
|
+
exports.pollRampTransaction = pollRampTransaction;
|
|
1739
|
+
exports.resolveKyc = resolveKyc;
|
|
1740
|
+
exports.startKyc = startKyc;
|
|
1618
1741
|
//# sourceMappingURL=index.js.map
|
|
1619
1742
|
//# sourceMappingURL=index.js.map
|