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