@partylayer/provider 0.6.0 → 0.6.1
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/README.md +14 -4
- package/dist/index.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +118 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +118 -100
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -513,7 +513,7 @@ var PartyLayerProvider = class {
|
|
|
513
513
|
};
|
|
514
514
|
|
|
515
515
|
// src/bridge.ts
|
|
516
|
-
var PROVIDER_VERSION = "0.6.
|
|
516
|
+
var PROVIDER_VERSION = "0.6.1" ;
|
|
517
517
|
function createProviderBridge(client) {
|
|
518
518
|
const eventBus = new CIP0103EventBus();
|
|
519
519
|
const pendingEmitted = /* @__PURE__ */ new Set();
|
|
@@ -578,9 +578,8 @@ async function handleRequest(client, args, eventBus, pendingEmitted) {
|
|
|
578
578
|
}
|
|
579
579
|
case "getActiveNetwork": {
|
|
580
580
|
const session = await client.getActiveSession();
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
);
|
|
581
|
+
if (!session) throw disconnected("No active session");
|
|
582
|
+
return toCAIP2Network(session.network);
|
|
584
583
|
}
|
|
585
584
|
case "listAccounts": {
|
|
586
585
|
const session = await client.getActiveSession();
|
|
@@ -605,61 +604,42 @@ async function handleRequest(client, args, eventBus, pendingEmitted) {
|
|
|
605
604
|
}
|
|
606
605
|
case "prepareExecute": {
|
|
607
606
|
const p = normalizeParams(params);
|
|
608
|
-
const
|
|
607
|
+
const session = await client.getActiveSession();
|
|
608
|
+
if (!session) throw disconnected("No active session");
|
|
609
|
+
const cmdId = nonempty(p.commandId) ? p.commandId : `cmd_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
610
|
+
if (pendingEmitted.has(cmdId)) throw resourceUnavailable("This commandId is already pending");
|
|
611
|
+
const payload = { ...p, commandId: cmdId };
|
|
609
612
|
pendingEmitted.add(cmdId);
|
|
610
|
-
eventBus.emit(CIP0103_EVENTS.TX_CHANGED, {
|
|
611
|
-
|
|
612
|
-
commandId: cmdId
|
|
613
|
-
});
|
|
613
|
+
eventBus.emit(CIP0103_EVENTS.TX_CHANGED, { status: "pending", commandId: cmdId });
|
|
614
|
+
let submitting = false;
|
|
614
615
|
try {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
party: partyId
|
|
626
|
-
}
|
|
627
|
-
});
|
|
616
|
+
let signedTx = payload;
|
|
617
|
+
if (!session.capabilitiesSnapshot || session.capabilitiesSnapshot.includes("signTransaction")) {
|
|
618
|
+
const signed = await client.signTransaction({ tx: payload });
|
|
619
|
+
if (signed.partyId !== void 0 && signed.partyId !== session.partyId) {
|
|
620
|
+
throw disconnected("Wallet account changed during signing");
|
|
621
|
+
}
|
|
622
|
+
signedTx = signed.signedTx;
|
|
623
|
+
if (signedTx === void 0) throw new Error("Wallet returned no signed transaction");
|
|
624
|
+
const event2 = signedEvent({ signature: signed.signature, signedBy: signed.signedBy, party: signed.partyId }, cmdId);
|
|
625
|
+
if (event2) eventBus.emit(CIP0103_EVENTS.TX_CHANGED, event2);
|
|
628
626
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
});
|
|
633
|
-
pendingEmitted.delete(cmdId);
|
|
634
|
-
eventBus.emit(CIP0103_EVENTS.TX_CHANGED, {
|
|
635
|
-
status: "executed",
|
|
636
|
-
commandId: cmdId,
|
|
637
|
-
payload: {
|
|
638
|
-
// All three are real identifiers — the receipt's update id, the
|
|
639
|
-
// wallet's command id, or the bridge's own command id for this
|
|
640
|
-
// operation. `String(receipt.transactionHash)` was the old tail
|
|
641
|
-
// and would now stringify `undefined`.
|
|
642
|
-
updateId: receipt.updateId ?? receipt.commandId ?? cmdId,
|
|
643
|
-
completionOffset: 0
|
|
644
|
-
}
|
|
645
|
-
});
|
|
646
|
-
} catch (submitErr) {
|
|
647
|
-
pendingEmitted.delete(cmdId);
|
|
648
|
-
eventBus.emit(CIP0103_EVENTS.TX_CHANGED, {
|
|
649
|
-
status: "failed",
|
|
650
|
-
commandId: cmdId
|
|
651
|
-
});
|
|
652
|
-
throw submitErr;
|
|
627
|
+
const current = await client.getActiveSession();
|
|
628
|
+
if (!current || current.sessionId !== session.sessionId || current.partyId !== session.partyId || current.network !== session.network) {
|
|
629
|
+
throw disconnected("Wallet session changed before submission");
|
|
653
630
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
631
|
+
submitting = true;
|
|
632
|
+
const receipt = await client.submitTransaction({ signedTx });
|
|
633
|
+
const event = executedEvent(receipt, cmdId);
|
|
634
|
+
if (event) eventBus.emit(CIP0103_EVENTS.TX_CHANGED, event);
|
|
635
|
+
} catch (reason) {
|
|
636
|
+
const code = reason?.code;
|
|
637
|
+
if (!submitting || code === 4001 || code === "USER_REJECTED" || code === -32003) {
|
|
638
|
+
eventBus.emit(CIP0103_EVENTS.TX_CHANGED, { status: "failed", commandId: cmdId });
|
|
661
639
|
}
|
|
662
|
-
throw
|
|
640
|
+
throw reason;
|
|
641
|
+
} finally {
|
|
642
|
+
pendingEmitted.delete(cmdId);
|
|
663
643
|
}
|
|
664
644
|
return void 0;
|
|
665
645
|
}
|
|
@@ -734,59 +714,51 @@ function wireEvents(client, eventBus, pendingEmitted) {
|
|
|
734
714
|
});
|
|
735
715
|
});
|
|
736
716
|
client.on("tx:status", (event) => {
|
|
737
|
-
const e = event;
|
|
738
|
-
if (!e
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
committed: "executed",
|
|
744
|
-
rejected: "failed",
|
|
745
|
-
failed: "failed"
|
|
746
|
-
};
|
|
747
|
-
const mappedStatus = statusMap[e.status] ?? "pending";
|
|
748
|
-
const commandId = String(e.txId);
|
|
749
|
-
if (mappedStatus === "pending" && pendingEmitted.has(commandId)) {
|
|
750
|
-
return;
|
|
751
|
-
}
|
|
752
|
-
if (mappedStatus === "executed" || mappedStatus === "failed") {
|
|
753
|
-
pendingEmitted.delete(commandId);
|
|
754
|
-
}
|
|
717
|
+
const e = record(event);
|
|
718
|
+
if (!e) return;
|
|
719
|
+
const raw = record(e.raw);
|
|
720
|
+
const tx = record(raw?.tx) ?? raw;
|
|
721
|
+
const commandId = nonempty(tx?.commandId) ? tx.commandId : e.txId;
|
|
722
|
+
if (!nonempty(commandId)) return;
|
|
755
723
|
let txEvent;
|
|
756
|
-
switch (
|
|
724
|
+
switch (e.status) {
|
|
725
|
+
case "pending":
|
|
726
|
+
case "submitted":
|
|
727
|
+
if (pendingEmitted.has(commandId)) return;
|
|
728
|
+
txEvent = { status: "pending", commandId };
|
|
729
|
+
break;
|
|
757
730
|
case "signed":
|
|
758
|
-
txEvent =
|
|
759
|
-
status: "signed",
|
|
760
|
-
commandId,
|
|
761
|
-
payload: {
|
|
762
|
-
signature: "",
|
|
763
|
-
signedBy: "",
|
|
764
|
-
party: ""
|
|
765
|
-
}
|
|
766
|
-
};
|
|
731
|
+
txEvent = signedEvent(tx, commandId);
|
|
767
732
|
break;
|
|
768
|
-
case "
|
|
769
|
-
|
|
770
|
-
txEvent = {
|
|
771
|
-
status: "executed",
|
|
772
|
-
commandId,
|
|
773
|
-
payload: {
|
|
774
|
-
updateId: raw?.updateId ?? raw?.commandId ?? commandId,
|
|
775
|
-
completionOffset: 0
|
|
776
|
-
}
|
|
777
|
-
};
|
|
733
|
+
case "committed":
|
|
734
|
+
txEvent = executedEvent(tx, commandId);
|
|
778
735
|
break;
|
|
779
|
-
|
|
736
|
+
case "rejected":
|
|
780
737
|
case "failed":
|
|
781
738
|
txEvent = { status: "failed", commandId };
|
|
782
739
|
break;
|
|
783
740
|
default:
|
|
784
|
-
|
|
785
|
-
break;
|
|
741
|
+
return;
|
|
786
742
|
}
|
|
787
|
-
eventBus.emit(CIP0103_EVENTS.TX_CHANGED, txEvent);
|
|
743
|
+
if (txEvent) eventBus.emit(CIP0103_EVENTS.TX_CHANGED, txEvent);
|
|
788
744
|
});
|
|
789
745
|
}
|
|
746
|
+
function record(value) {
|
|
747
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
748
|
+
}
|
|
749
|
+
function nonempty(value) {
|
|
750
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
751
|
+
}
|
|
752
|
+
function signedEvent(value, commandId) {
|
|
753
|
+
const tx = record(value);
|
|
754
|
+
const p = record(tx?.payload) ?? tx;
|
|
755
|
+
return nonempty(p?.signature) && nonempty(p?.signedBy) && nonempty(p?.party) ? { status: "signed", commandId, payload: { signature: p.signature, signedBy: p.signedBy, party: p.party } } : null;
|
|
756
|
+
}
|
|
757
|
+
function executedEvent(value, commandId) {
|
|
758
|
+
const tx = record(value);
|
|
759
|
+
const p = record(tx?.payload) ?? tx;
|
|
760
|
+
return nonempty(p?.updateId) && typeof p.completionOffset === "number" && Number.isSafeInteger(p.completionOffset) && p.completionOffset >= 0 ? { status: "executed", commandId, payload: { updateId: p.updateId, completionOffset: p.completionOffset } } : null;
|
|
761
|
+
}
|
|
790
762
|
function normalizeParams(params) {
|
|
791
763
|
if (!params) return {};
|
|
792
764
|
if (Array.isArray(params)) return params[0] ?? {};
|
|
@@ -818,11 +790,33 @@ function createExtensionChannelProvider(options = {}) {
|
|
|
818
790
|
const eventBus = new CIP0103EventBus();
|
|
819
791
|
const channelId = `pl-${++channelSeq}-${target ?? "ext"}`;
|
|
820
792
|
let requestSeq = 0;
|
|
793
|
+
let listening = false;
|
|
794
|
+
let destroyed = false;
|
|
795
|
+
const subscribedEvents = /* @__PURE__ */ new Set();
|
|
796
|
+
function listen() {
|
|
797
|
+
if (!listening && typeof window !== "undefined") {
|
|
798
|
+
window.addEventListener("message", onMessage);
|
|
799
|
+
listening = true;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
function detachIfIdle() {
|
|
803
|
+
if (pending.size > 0 || [...subscribedEvents].some((name) => eventBus.listenerCount(name) > 0)) return;
|
|
804
|
+
if (listening && typeof window !== "undefined") window.removeEventListener("message", onMessage);
|
|
805
|
+
listening = false;
|
|
806
|
+
}
|
|
821
807
|
const pending = /* @__PURE__ */ new Map();
|
|
822
808
|
function onMessage(event) {
|
|
823
809
|
if (event.source !== window) return;
|
|
824
810
|
const selfOrigin = typeof window !== "undefined" ? window.location?.origin : void 0;
|
|
825
811
|
if (selfOrigin && selfOrigin !== "null" && event.origin !== selfOrigin) return;
|
|
812
|
+
const notification = event.data;
|
|
813
|
+
if (notification?.type === SPLICE_WALLET_REQUEST && notification.request?.jsonrpc === "2.0" && notification.request.id == null && (!target || notification.target === target)) {
|
|
814
|
+
const method = notification.request.method;
|
|
815
|
+
if (method && ["statusChanged", "accountsChanged", "txChanged", "connected"].includes(method)) {
|
|
816
|
+
eventBus.emit(method, notification.request.params);
|
|
817
|
+
}
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
826
820
|
const data = event.data;
|
|
827
821
|
if (!data || data.type !== SPLICE_WALLET_RESPONSE || !data.response) return;
|
|
828
822
|
const { id, result, error } = data.response;
|
|
@@ -831,6 +825,7 @@ function createExtensionChannelProvider(options = {}) {
|
|
|
831
825
|
if (!entry) return;
|
|
832
826
|
pending.delete(String(id));
|
|
833
827
|
clearTimeout(entry.timer);
|
|
828
|
+
detachIfIdle();
|
|
834
829
|
if (error) {
|
|
835
830
|
entry.reject(
|
|
836
831
|
new ProviderRpcError(
|
|
@@ -843,24 +838,24 @@ function createExtensionChannelProvider(options = {}) {
|
|
|
843
838
|
entry.resolve(result);
|
|
844
839
|
}
|
|
845
840
|
}
|
|
846
|
-
if (typeof window !== "undefined") {
|
|
847
|
-
window.addEventListener("message", onMessage);
|
|
848
|
-
}
|
|
849
841
|
function postTargetOrigin() {
|
|
850
842
|
const origin = typeof window !== "undefined" ? window.location?.origin : void 0;
|
|
851
843
|
return origin && origin !== "null" ? origin : "*";
|
|
852
844
|
}
|
|
853
845
|
const provider = {
|
|
854
846
|
request(args) {
|
|
847
|
+
if (destroyed) return Promise.reject(new ProviderRpcError("Extension channel was destroyed", RPC_ERRORS.DISCONNECTED));
|
|
855
848
|
if (typeof window === "undefined") {
|
|
856
849
|
return Promise.reject(
|
|
857
850
|
new ProviderRpcError("No window: extension channel unavailable", JSON_RPC_ERRORS.INTERNAL_ERROR)
|
|
858
851
|
);
|
|
859
852
|
}
|
|
853
|
+
listen();
|
|
860
854
|
const id = `${channelId}-${++requestSeq}`;
|
|
861
855
|
return new Promise((resolve, reject) => {
|
|
862
856
|
const timer = setTimeout(() => {
|
|
863
857
|
pending.delete(id);
|
|
858
|
+
detachIfIdle();
|
|
864
859
|
reject(
|
|
865
860
|
new ProviderRpcError(
|
|
866
861
|
`Wallet request "${args.method}" timed out after ${timeoutMs}ms`,
|
|
@@ -879,11 +874,21 @@ function createExtensionChannelProvider(options = {}) {
|
|
|
879
874
|
},
|
|
880
875
|
...target ? { target } : {}
|
|
881
876
|
};
|
|
882
|
-
|
|
877
|
+
try {
|
|
878
|
+
window.postMessage(message, postTargetOrigin());
|
|
879
|
+
} catch (error) {
|
|
880
|
+
pending.delete(id);
|
|
881
|
+
clearTimeout(timer);
|
|
882
|
+
detachIfIdle();
|
|
883
|
+
reject(error);
|
|
884
|
+
}
|
|
883
885
|
});
|
|
884
886
|
},
|
|
885
887
|
on(event, listener) {
|
|
888
|
+
if (destroyed) return provider;
|
|
886
889
|
eventBus.on(event, listener);
|
|
890
|
+
subscribedEvents.add(event);
|
|
891
|
+
listen();
|
|
887
892
|
return provider;
|
|
888
893
|
},
|
|
889
894
|
emit(event, ...args) {
|
|
@@ -891,7 +896,20 @@ function createExtensionChannelProvider(options = {}) {
|
|
|
891
896
|
},
|
|
892
897
|
removeListener(event, listener) {
|
|
893
898
|
eventBus.removeListener(event, listener);
|
|
899
|
+
detachIfIdle();
|
|
894
900
|
return provider;
|
|
901
|
+
},
|
|
902
|
+
destroy() {
|
|
903
|
+
if (destroyed) return;
|
|
904
|
+
destroyed = true;
|
|
905
|
+
eventBus.removeAllListeners();
|
|
906
|
+
subscribedEvents.clear();
|
|
907
|
+
for (const entry of pending.values()) {
|
|
908
|
+
clearTimeout(entry.timer);
|
|
909
|
+
entry.reject(new ProviderRpcError("Extension channel was destroyed", RPC_ERRORS.DISCONNECTED));
|
|
910
|
+
}
|
|
911
|
+
pending.clear();
|
|
912
|
+
detachIfIdle();
|
|
895
913
|
}
|
|
896
914
|
};
|
|
897
915
|
eventBus.setOwner(provider);
|