@zyfai/sdk 0.1.6 → 0.1.8
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 +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +134 -9
- package/dist/index.mjs +134 -9
- package/package.json +10 -2
package/dist/index.d.mts
CHANGED
|
@@ -54,8 +54,6 @@ interface AddSessionKeyResponse {
|
|
|
54
54
|
}
|
|
55
55
|
interface SessionKeyResponse {
|
|
56
56
|
success: boolean;
|
|
57
|
-
/** Session key address (not available when alreadyActive is true) */
|
|
58
|
-
sessionKeyAddress?: Address;
|
|
59
57
|
/** Signature (not available when alreadyActive is true) */
|
|
60
58
|
signature?: Hex;
|
|
61
59
|
sessionNonces?: bigint[];
|
|
@@ -410,10 +408,10 @@ declare class ZyfaiSDK {
|
|
|
410
408
|
private signer;
|
|
411
409
|
private walletClient;
|
|
412
410
|
private bundlerApiKey?;
|
|
413
|
-
private isAuthenticated;
|
|
414
411
|
private authenticatedUserId;
|
|
415
412
|
private hasActiveSessionKey;
|
|
416
413
|
private environment;
|
|
414
|
+
private currentProvider;
|
|
417
415
|
constructor(config: SDKConfig | string);
|
|
418
416
|
/**
|
|
419
417
|
* Authenticate user with SIWE (Sign-In with Ethereum) & JWT token
|
|
@@ -439,6 +437,27 @@ declare class ZyfaiSDK {
|
|
|
439
437
|
* ```
|
|
440
438
|
*/
|
|
441
439
|
updateUserProfile(request: UpdateUserProfileRequest): Promise<UpdateUserProfileResponse>;
|
|
440
|
+
/**
|
|
441
|
+
* Initialize user after Safe deployment
|
|
442
|
+
* This method is automatically called after deploySafe to initialize user state
|
|
443
|
+
*
|
|
444
|
+
* @param smartWallet - Safe smart wallet address
|
|
445
|
+
* @param chainId - Target chain ID
|
|
446
|
+
* @returns Initialization response
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```typescript
|
|
450
|
+
* await sdk.initializeUser("0x1396730...", 8453);
|
|
451
|
+
* ```
|
|
452
|
+
* @internal
|
|
453
|
+
*/
|
|
454
|
+
private initializeUser;
|
|
455
|
+
/**
|
|
456
|
+
* Handle account changes from wallet provider
|
|
457
|
+
* Resets authentication state when wallet is switched
|
|
458
|
+
* @private
|
|
459
|
+
*/
|
|
460
|
+
private handleAccountsChanged;
|
|
442
461
|
/**
|
|
443
462
|
* Connect account for signing transactions
|
|
444
463
|
* Accepts either a private key string or a modern wallet provider
|
|
@@ -511,6 +530,14 @@ declare class ZyfaiSDK {
|
|
|
511
530
|
* @private
|
|
512
531
|
*/
|
|
513
532
|
private signSessionKey;
|
|
533
|
+
/**
|
|
534
|
+
* Update user protocols with available protocols from the chain
|
|
535
|
+
* This method is automatically called before activating session key
|
|
536
|
+
*
|
|
537
|
+
* @param chainId - Target chain ID
|
|
538
|
+
* @internal
|
|
539
|
+
*/
|
|
540
|
+
private updateUserProtocols;
|
|
514
541
|
/**
|
|
515
542
|
* Activate session key via ZyFAI API
|
|
516
543
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -54,8 +54,6 @@ interface AddSessionKeyResponse {
|
|
|
54
54
|
}
|
|
55
55
|
interface SessionKeyResponse {
|
|
56
56
|
success: boolean;
|
|
57
|
-
/** Session key address (not available when alreadyActive is true) */
|
|
58
|
-
sessionKeyAddress?: Address;
|
|
59
57
|
/** Signature (not available when alreadyActive is true) */
|
|
60
58
|
signature?: Hex;
|
|
61
59
|
sessionNonces?: bigint[];
|
|
@@ -410,10 +408,10 @@ declare class ZyfaiSDK {
|
|
|
410
408
|
private signer;
|
|
411
409
|
private walletClient;
|
|
412
410
|
private bundlerApiKey?;
|
|
413
|
-
private isAuthenticated;
|
|
414
411
|
private authenticatedUserId;
|
|
415
412
|
private hasActiveSessionKey;
|
|
416
413
|
private environment;
|
|
414
|
+
private currentProvider;
|
|
417
415
|
constructor(config: SDKConfig | string);
|
|
418
416
|
/**
|
|
419
417
|
* Authenticate user with SIWE (Sign-In with Ethereum) & JWT token
|
|
@@ -439,6 +437,27 @@ declare class ZyfaiSDK {
|
|
|
439
437
|
* ```
|
|
440
438
|
*/
|
|
441
439
|
updateUserProfile(request: UpdateUserProfileRequest): Promise<UpdateUserProfileResponse>;
|
|
440
|
+
/**
|
|
441
|
+
* Initialize user after Safe deployment
|
|
442
|
+
* This method is automatically called after deploySafe to initialize user state
|
|
443
|
+
*
|
|
444
|
+
* @param smartWallet - Safe smart wallet address
|
|
445
|
+
* @param chainId - Target chain ID
|
|
446
|
+
* @returns Initialization response
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```typescript
|
|
450
|
+
* await sdk.initializeUser("0x1396730...", 8453);
|
|
451
|
+
* ```
|
|
452
|
+
* @internal
|
|
453
|
+
*/
|
|
454
|
+
private initializeUser;
|
|
455
|
+
/**
|
|
456
|
+
* Handle account changes from wallet provider
|
|
457
|
+
* Resets authentication state when wallet is switched
|
|
458
|
+
* @private
|
|
459
|
+
*/
|
|
460
|
+
private handleAccountsChanged;
|
|
442
461
|
/**
|
|
443
462
|
* Connect account for signing transactions
|
|
444
463
|
* Accepts either a private key string or a modern wallet provider
|
|
@@ -511,6 +530,14 @@ declare class ZyfaiSDK {
|
|
|
511
530
|
* @private
|
|
512
531
|
*/
|
|
513
532
|
private signSessionKey;
|
|
533
|
+
/**
|
|
534
|
+
* Update user protocols with available protocols from the chain
|
|
535
|
+
* This method is automatically called before activating session key
|
|
536
|
+
*
|
|
537
|
+
* @param chainId - Target chain ID
|
|
538
|
+
* @internal
|
|
539
|
+
*/
|
|
540
|
+
private updateUserProtocols;
|
|
514
541
|
/**
|
|
515
542
|
* Activate session key via ZyFAI API
|
|
516
543
|
*/
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,7 @@ var ENDPOINTS = {
|
|
|
57
57
|
AUTH_CHALLENGE: "/auth/challenge",
|
|
58
58
|
// User
|
|
59
59
|
USER_ME: "/users/me",
|
|
60
|
+
USER_INITIALIZE: "/users/initialize",
|
|
60
61
|
USER_WITHDRAW: "/users/withdraw",
|
|
61
62
|
PARTIAL_WITHDRAW: "/users/partial-withdraw",
|
|
62
63
|
// Session Keys
|
|
@@ -620,14 +621,15 @@ var signSessionKey = async (config, sessions, allPublicClients) => {
|
|
|
620
621
|
// src/core/ZyfaiSDK.ts
|
|
621
622
|
var import_siwe = require("siwe");
|
|
622
623
|
var ZyfaiSDK = class {
|
|
623
|
-
//
|
|
624
|
+
// Store reference to current provider for event handling
|
|
624
625
|
constructor(config) {
|
|
625
626
|
this.signer = null;
|
|
626
627
|
this.walletClient = null;
|
|
627
|
-
this.isAuthenticated = false;
|
|
628
628
|
this.authenticatedUserId = null;
|
|
629
|
-
//
|
|
629
|
+
// If non-null, user is authenticated
|
|
630
630
|
this.hasActiveSessionKey = false;
|
|
631
|
+
// TODO: The environment should be removed. Having the same key for staging and production is not ideal, but for now it's fine.
|
|
632
|
+
this.currentProvider = null;
|
|
631
633
|
const sdkConfig = typeof config === "string" ? { apiKey: config } : config;
|
|
632
634
|
const { apiKey, dataApiKey, environment, bundlerApiKey } = sdkConfig;
|
|
633
635
|
if (!apiKey) {
|
|
@@ -646,7 +648,7 @@ var ZyfaiSDK = class {
|
|
|
646
648
|
*/
|
|
647
649
|
async authenticateUser() {
|
|
648
650
|
try {
|
|
649
|
-
if (this.
|
|
651
|
+
if (this.authenticatedUserId !== null) {
|
|
650
652
|
return;
|
|
651
653
|
}
|
|
652
654
|
const walletClient = this.getWalletClient();
|
|
@@ -685,14 +687,13 @@ var ZyfaiSDK = class {
|
|
|
685
687
|
signature
|
|
686
688
|
}
|
|
687
689
|
);
|
|
688
|
-
const authToken = loginResponse.accessToken
|
|
690
|
+
const authToken = loginResponse.accessToken;
|
|
689
691
|
if (!authToken) {
|
|
690
692
|
throw new Error("Authentication response missing access token");
|
|
691
693
|
}
|
|
692
694
|
this.httpClient.setAuthToken(authToken);
|
|
693
695
|
this.authenticatedUserId = loginResponse.userId || null;
|
|
694
696
|
this.hasActiveSessionKey = loginResponse.hasActiveSessionKey || false;
|
|
695
|
-
this.isAuthenticated = true;
|
|
696
697
|
} catch (error) {
|
|
697
698
|
throw new Error(
|
|
698
699
|
`Failed to authenticate user: ${error.message}`
|
|
@@ -733,6 +734,80 @@ var ZyfaiSDK = class {
|
|
|
733
734
|
);
|
|
734
735
|
}
|
|
735
736
|
}
|
|
737
|
+
/**
|
|
738
|
+
* Initialize user after Safe deployment
|
|
739
|
+
* This method is automatically called after deploySafe to initialize user state
|
|
740
|
+
*
|
|
741
|
+
* @param smartWallet - Safe smart wallet address
|
|
742
|
+
* @param chainId - Target chain ID
|
|
743
|
+
* @returns Initialization response
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* await sdk.initializeUser("0x1396730...", 8453);
|
|
748
|
+
* ```
|
|
749
|
+
* @internal
|
|
750
|
+
*/
|
|
751
|
+
async initializeUser(smartWallet, chainId) {
|
|
752
|
+
try {
|
|
753
|
+
await this.authenticateUser();
|
|
754
|
+
const response = await this.httpClient.post(
|
|
755
|
+
ENDPOINTS.USER_INITIALIZE,
|
|
756
|
+
{
|
|
757
|
+
smartWallet,
|
|
758
|
+
chainId
|
|
759
|
+
}
|
|
760
|
+
);
|
|
761
|
+
return {
|
|
762
|
+
success: true,
|
|
763
|
+
userId: response.userId || response.id,
|
|
764
|
+
smartWallet: response.smartWallet,
|
|
765
|
+
chainId: response.chainId,
|
|
766
|
+
message: response.message
|
|
767
|
+
};
|
|
768
|
+
} catch (error) {
|
|
769
|
+
throw new Error(
|
|
770
|
+
`Failed to initialize user: ${error.message}`
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Handle account changes from wallet provider
|
|
776
|
+
* Resets authentication state when wallet is switched
|
|
777
|
+
* @private
|
|
778
|
+
*/
|
|
779
|
+
async handleAccountsChanged(accounts) {
|
|
780
|
+
if (!accounts || accounts.length === 0) {
|
|
781
|
+
await this.disconnectAccount();
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
const newAddress = accounts[0];
|
|
785
|
+
const currentAddress = this.walletClient?.account?.address;
|
|
786
|
+
if (currentAddress && newAddress.toLowerCase() === currentAddress.toLowerCase()) {
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
this.authenticatedUserId = null;
|
|
790
|
+
this.hasActiveSessionKey = false;
|
|
791
|
+
this.httpClient.clearAuthToken();
|
|
792
|
+
if (this.walletClient && this.currentProvider) {
|
|
793
|
+
const chainConfig = getChainConfig(
|
|
794
|
+
this.walletClient.chain?.id || 42161
|
|
795
|
+
);
|
|
796
|
+
this.walletClient = (0, import_viem4.createWalletClient)({
|
|
797
|
+
account: newAddress,
|
|
798
|
+
chain: chainConfig.chain,
|
|
799
|
+
transport: (0, import_viem4.custom)(this.currentProvider)
|
|
800
|
+
});
|
|
801
|
+
try {
|
|
802
|
+
await this.authenticateUser();
|
|
803
|
+
} catch (error) {
|
|
804
|
+
console.warn(
|
|
805
|
+
"Failed to authenticate after wallet switch:",
|
|
806
|
+
error.message
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
736
811
|
/**
|
|
737
812
|
* Connect account for signing transactions
|
|
738
813
|
* Accepts either a private key string or a modern wallet provider
|
|
@@ -754,8 +829,14 @@ var ZyfaiSDK = class {
|
|
|
754
829
|
if (!isSupportedChain(chainId)) {
|
|
755
830
|
throw new Error(`Unsupported chain ID: ${chainId}`);
|
|
756
831
|
}
|
|
757
|
-
this.
|
|
832
|
+
this.authenticatedUserId = null;
|
|
758
833
|
this.httpClient.clearAuthToken();
|
|
834
|
+
if (this.currentProvider?.removeAllListeners) {
|
|
835
|
+
try {
|
|
836
|
+
this.currentProvider.removeAllListeners("accountsChanged");
|
|
837
|
+
} catch (error) {
|
|
838
|
+
}
|
|
839
|
+
}
|
|
759
840
|
const chainConfig = getChainConfig(chainId);
|
|
760
841
|
let connectedAddress;
|
|
761
842
|
if (typeof account === "string") {
|
|
@@ -770,6 +851,7 @@ var ZyfaiSDK = class {
|
|
|
770
851
|
transport: (0, import_viem4.http)(chainConfig.rpcUrl)
|
|
771
852
|
});
|
|
772
853
|
connectedAddress = this.signer.address;
|
|
854
|
+
this.currentProvider = null;
|
|
773
855
|
} else {
|
|
774
856
|
const provider = account;
|
|
775
857
|
if (!provider) {
|
|
@@ -790,6 +872,10 @@ var ZyfaiSDK = class {
|
|
|
790
872
|
transport: (0, import_viem4.custom)(provider)
|
|
791
873
|
});
|
|
792
874
|
connectedAddress = accounts[0];
|
|
875
|
+
this.currentProvider = provider;
|
|
876
|
+
if (provider.on) {
|
|
877
|
+
provider.on("accountsChanged", this.handleAccountsChanged.bind(this));
|
|
878
|
+
}
|
|
793
879
|
} else if (provider.account && provider.transport) {
|
|
794
880
|
this.walletClient = (0, import_viem4.createWalletClient)({
|
|
795
881
|
account: provider.account,
|
|
@@ -797,6 +883,7 @@ var ZyfaiSDK = class {
|
|
|
797
883
|
transport: provider.transport
|
|
798
884
|
});
|
|
799
885
|
connectedAddress = provider.account.address;
|
|
886
|
+
this.currentProvider = null;
|
|
800
887
|
} else {
|
|
801
888
|
throw new Error(
|
|
802
889
|
"Invalid wallet provider. Expected EIP-1193 provider or viem WalletClient."
|
|
@@ -817,9 +904,15 @@ var ZyfaiSDK = class {
|
|
|
817
904
|
* ```
|
|
818
905
|
*/
|
|
819
906
|
async disconnectAccount() {
|
|
907
|
+
if (this.currentProvider?.removeAllListeners) {
|
|
908
|
+
try {
|
|
909
|
+
this.currentProvider.removeAllListeners("accountsChanged");
|
|
910
|
+
} catch (error) {
|
|
911
|
+
}
|
|
912
|
+
}
|
|
820
913
|
this.signer = null;
|
|
821
914
|
this.walletClient = null;
|
|
822
|
-
this.
|
|
915
|
+
this.currentProvider = null;
|
|
823
916
|
this.authenticatedUserId = null;
|
|
824
917
|
this.hasActiveSessionKey = false;
|
|
825
918
|
this.httpClient.clearAuthToken();
|
|
@@ -946,6 +1039,14 @@ var ZyfaiSDK = class {
|
|
|
946
1039
|
updateError.message
|
|
947
1040
|
);
|
|
948
1041
|
}
|
|
1042
|
+
try {
|
|
1043
|
+
await this.initializeUser(deploymentResult.safeAddress, chainId);
|
|
1044
|
+
} catch (initError) {
|
|
1045
|
+
console.warn(
|
|
1046
|
+
"Failed to initialize user after Safe deployment:",
|
|
1047
|
+
initError.message
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
949
1050
|
return {
|
|
950
1051
|
success: true,
|
|
951
1052
|
safeAddress: deploymentResult.safeAddress,
|
|
@@ -1006,6 +1107,7 @@ var ZyfaiSDK = class {
|
|
|
1006
1107
|
if (!signatureResult.signature) {
|
|
1007
1108
|
throw new Error("Failed to obtain session key signature");
|
|
1008
1109
|
}
|
|
1110
|
+
await this.updateUserProtocols(chainId);
|
|
1009
1111
|
const activation = await this.activateSessionKey(
|
|
1010
1112
|
signatureResult.signature,
|
|
1011
1113
|
signatureResult.sessionNonces
|
|
@@ -1072,7 +1174,6 @@ var ZyfaiSDK = class {
|
|
|
1072
1174
|
});
|
|
1073
1175
|
return {
|
|
1074
1176
|
success: true,
|
|
1075
|
-
sessionKeyAddress: safeAddress,
|
|
1076
1177
|
signature,
|
|
1077
1178
|
sessionNonces
|
|
1078
1179
|
};
|
|
@@ -1082,6 +1183,30 @@ var ZyfaiSDK = class {
|
|
|
1082
1183
|
);
|
|
1083
1184
|
}
|
|
1084
1185
|
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Update user protocols with available protocols from the chain
|
|
1188
|
+
* This method is automatically called before activating session key
|
|
1189
|
+
*
|
|
1190
|
+
* @param chainId - Target chain ID
|
|
1191
|
+
* @internal
|
|
1192
|
+
*/
|
|
1193
|
+
async updateUserProtocols(chainId) {
|
|
1194
|
+
try {
|
|
1195
|
+
const protocolsResponse = await this.getAvailableProtocols(chainId);
|
|
1196
|
+
if (!protocolsResponse.protocols || protocolsResponse.protocols.length === 0) {
|
|
1197
|
+
console.warn(`No protocols available for chain ${chainId}`);
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
const protocolIds = protocolsResponse.protocols.map((p) => p.id);
|
|
1201
|
+
await this.updateUserProfile({
|
|
1202
|
+
protocols: protocolIds
|
|
1203
|
+
});
|
|
1204
|
+
} catch (error) {
|
|
1205
|
+
console.warn(
|
|
1206
|
+
`Failed to update user protocols: ${error.message}`
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1085
1210
|
/**
|
|
1086
1211
|
* Activate session key via ZyFAI API
|
|
1087
1212
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -18,6 +18,7 @@ var ENDPOINTS = {
|
|
|
18
18
|
AUTH_CHALLENGE: "/auth/challenge",
|
|
19
19
|
// User
|
|
20
20
|
USER_ME: "/users/me",
|
|
21
|
+
USER_INITIALIZE: "/users/initialize",
|
|
21
22
|
USER_WITHDRAW: "/users/withdraw",
|
|
22
23
|
PARTIAL_WITHDRAW: "/users/partial-withdraw",
|
|
23
24
|
// Session Keys
|
|
@@ -599,14 +600,15 @@ var signSessionKey = async (config, sessions, allPublicClients) => {
|
|
|
599
600
|
// src/core/ZyfaiSDK.ts
|
|
600
601
|
import { SiweMessage } from "siwe";
|
|
601
602
|
var ZyfaiSDK = class {
|
|
602
|
-
//
|
|
603
|
+
// Store reference to current provider for event handling
|
|
603
604
|
constructor(config) {
|
|
604
605
|
this.signer = null;
|
|
605
606
|
this.walletClient = null;
|
|
606
|
-
this.isAuthenticated = false;
|
|
607
607
|
this.authenticatedUserId = null;
|
|
608
|
-
//
|
|
608
|
+
// If non-null, user is authenticated
|
|
609
609
|
this.hasActiveSessionKey = false;
|
|
610
|
+
// TODO: The environment should be removed. Having the same key for staging and production is not ideal, but for now it's fine.
|
|
611
|
+
this.currentProvider = null;
|
|
610
612
|
const sdkConfig = typeof config === "string" ? { apiKey: config } : config;
|
|
611
613
|
const { apiKey, dataApiKey, environment, bundlerApiKey } = sdkConfig;
|
|
612
614
|
if (!apiKey) {
|
|
@@ -625,7 +627,7 @@ var ZyfaiSDK = class {
|
|
|
625
627
|
*/
|
|
626
628
|
async authenticateUser() {
|
|
627
629
|
try {
|
|
628
|
-
if (this.
|
|
630
|
+
if (this.authenticatedUserId !== null) {
|
|
629
631
|
return;
|
|
630
632
|
}
|
|
631
633
|
const walletClient = this.getWalletClient();
|
|
@@ -664,14 +666,13 @@ var ZyfaiSDK = class {
|
|
|
664
666
|
signature
|
|
665
667
|
}
|
|
666
668
|
);
|
|
667
|
-
const authToken = loginResponse.accessToken
|
|
669
|
+
const authToken = loginResponse.accessToken;
|
|
668
670
|
if (!authToken) {
|
|
669
671
|
throw new Error("Authentication response missing access token");
|
|
670
672
|
}
|
|
671
673
|
this.httpClient.setAuthToken(authToken);
|
|
672
674
|
this.authenticatedUserId = loginResponse.userId || null;
|
|
673
675
|
this.hasActiveSessionKey = loginResponse.hasActiveSessionKey || false;
|
|
674
|
-
this.isAuthenticated = true;
|
|
675
676
|
} catch (error) {
|
|
676
677
|
throw new Error(
|
|
677
678
|
`Failed to authenticate user: ${error.message}`
|
|
@@ -712,6 +713,80 @@ var ZyfaiSDK = class {
|
|
|
712
713
|
);
|
|
713
714
|
}
|
|
714
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Initialize user after Safe deployment
|
|
718
|
+
* This method is automatically called after deploySafe to initialize user state
|
|
719
|
+
*
|
|
720
|
+
* @param smartWallet - Safe smart wallet address
|
|
721
|
+
* @param chainId - Target chain ID
|
|
722
|
+
* @returns Initialization response
|
|
723
|
+
*
|
|
724
|
+
* @example
|
|
725
|
+
* ```typescript
|
|
726
|
+
* await sdk.initializeUser("0x1396730...", 8453);
|
|
727
|
+
* ```
|
|
728
|
+
* @internal
|
|
729
|
+
*/
|
|
730
|
+
async initializeUser(smartWallet, chainId) {
|
|
731
|
+
try {
|
|
732
|
+
await this.authenticateUser();
|
|
733
|
+
const response = await this.httpClient.post(
|
|
734
|
+
ENDPOINTS.USER_INITIALIZE,
|
|
735
|
+
{
|
|
736
|
+
smartWallet,
|
|
737
|
+
chainId
|
|
738
|
+
}
|
|
739
|
+
);
|
|
740
|
+
return {
|
|
741
|
+
success: true,
|
|
742
|
+
userId: response.userId || response.id,
|
|
743
|
+
smartWallet: response.smartWallet,
|
|
744
|
+
chainId: response.chainId,
|
|
745
|
+
message: response.message
|
|
746
|
+
};
|
|
747
|
+
} catch (error) {
|
|
748
|
+
throw new Error(
|
|
749
|
+
`Failed to initialize user: ${error.message}`
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Handle account changes from wallet provider
|
|
755
|
+
* Resets authentication state when wallet is switched
|
|
756
|
+
* @private
|
|
757
|
+
*/
|
|
758
|
+
async handleAccountsChanged(accounts) {
|
|
759
|
+
if (!accounts || accounts.length === 0) {
|
|
760
|
+
await this.disconnectAccount();
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
const newAddress = accounts[0];
|
|
764
|
+
const currentAddress = this.walletClient?.account?.address;
|
|
765
|
+
if (currentAddress && newAddress.toLowerCase() === currentAddress.toLowerCase()) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
this.authenticatedUserId = null;
|
|
769
|
+
this.hasActiveSessionKey = false;
|
|
770
|
+
this.httpClient.clearAuthToken();
|
|
771
|
+
if (this.walletClient && this.currentProvider) {
|
|
772
|
+
const chainConfig = getChainConfig(
|
|
773
|
+
this.walletClient.chain?.id || 42161
|
|
774
|
+
);
|
|
775
|
+
this.walletClient = createWalletClient({
|
|
776
|
+
account: newAddress,
|
|
777
|
+
chain: chainConfig.chain,
|
|
778
|
+
transport: custom(this.currentProvider)
|
|
779
|
+
});
|
|
780
|
+
try {
|
|
781
|
+
await this.authenticateUser();
|
|
782
|
+
} catch (error) {
|
|
783
|
+
console.warn(
|
|
784
|
+
"Failed to authenticate after wallet switch:",
|
|
785
|
+
error.message
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
715
790
|
/**
|
|
716
791
|
* Connect account for signing transactions
|
|
717
792
|
* Accepts either a private key string or a modern wallet provider
|
|
@@ -733,8 +808,14 @@ var ZyfaiSDK = class {
|
|
|
733
808
|
if (!isSupportedChain(chainId)) {
|
|
734
809
|
throw new Error(`Unsupported chain ID: ${chainId}`);
|
|
735
810
|
}
|
|
736
|
-
this.
|
|
811
|
+
this.authenticatedUserId = null;
|
|
737
812
|
this.httpClient.clearAuthToken();
|
|
813
|
+
if (this.currentProvider?.removeAllListeners) {
|
|
814
|
+
try {
|
|
815
|
+
this.currentProvider.removeAllListeners("accountsChanged");
|
|
816
|
+
} catch (error) {
|
|
817
|
+
}
|
|
818
|
+
}
|
|
738
819
|
const chainConfig = getChainConfig(chainId);
|
|
739
820
|
let connectedAddress;
|
|
740
821
|
if (typeof account === "string") {
|
|
@@ -749,6 +830,7 @@ var ZyfaiSDK = class {
|
|
|
749
830
|
transport: http3(chainConfig.rpcUrl)
|
|
750
831
|
});
|
|
751
832
|
connectedAddress = this.signer.address;
|
|
833
|
+
this.currentProvider = null;
|
|
752
834
|
} else {
|
|
753
835
|
const provider = account;
|
|
754
836
|
if (!provider) {
|
|
@@ -769,6 +851,10 @@ var ZyfaiSDK = class {
|
|
|
769
851
|
transport: custom(provider)
|
|
770
852
|
});
|
|
771
853
|
connectedAddress = accounts[0];
|
|
854
|
+
this.currentProvider = provider;
|
|
855
|
+
if (provider.on) {
|
|
856
|
+
provider.on("accountsChanged", this.handleAccountsChanged.bind(this));
|
|
857
|
+
}
|
|
772
858
|
} else if (provider.account && provider.transport) {
|
|
773
859
|
this.walletClient = createWalletClient({
|
|
774
860
|
account: provider.account,
|
|
@@ -776,6 +862,7 @@ var ZyfaiSDK = class {
|
|
|
776
862
|
transport: provider.transport
|
|
777
863
|
});
|
|
778
864
|
connectedAddress = provider.account.address;
|
|
865
|
+
this.currentProvider = null;
|
|
779
866
|
} else {
|
|
780
867
|
throw new Error(
|
|
781
868
|
"Invalid wallet provider. Expected EIP-1193 provider or viem WalletClient."
|
|
@@ -796,9 +883,15 @@ var ZyfaiSDK = class {
|
|
|
796
883
|
* ```
|
|
797
884
|
*/
|
|
798
885
|
async disconnectAccount() {
|
|
886
|
+
if (this.currentProvider?.removeAllListeners) {
|
|
887
|
+
try {
|
|
888
|
+
this.currentProvider.removeAllListeners("accountsChanged");
|
|
889
|
+
} catch (error) {
|
|
890
|
+
}
|
|
891
|
+
}
|
|
799
892
|
this.signer = null;
|
|
800
893
|
this.walletClient = null;
|
|
801
|
-
this.
|
|
894
|
+
this.currentProvider = null;
|
|
802
895
|
this.authenticatedUserId = null;
|
|
803
896
|
this.hasActiveSessionKey = false;
|
|
804
897
|
this.httpClient.clearAuthToken();
|
|
@@ -925,6 +1018,14 @@ var ZyfaiSDK = class {
|
|
|
925
1018
|
updateError.message
|
|
926
1019
|
);
|
|
927
1020
|
}
|
|
1021
|
+
try {
|
|
1022
|
+
await this.initializeUser(deploymentResult.safeAddress, chainId);
|
|
1023
|
+
} catch (initError) {
|
|
1024
|
+
console.warn(
|
|
1025
|
+
"Failed to initialize user after Safe deployment:",
|
|
1026
|
+
initError.message
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
928
1029
|
return {
|
|
929
1030
|
success: true,
|
|
930
1031
|
safeAddress: deploymentResult.safeAddress,
|
|
@@ -985,6 +1086,7 @@ var ZyfaiSDK = class {
|
|
|
985
1086
|
if (!signatureResult.signature) {
|
|
986
1087
|
throw new Error("Failed to obtain session key signature");
|
|
987
1088
|
}
|
|
1089
|
+
await this.updateUserProtocols(chainId);
|
|
988
1090
|
const activation = await this.activateSessionKey(
|
|
989
1091
|
signatureResult.signature,
|
|
990
1092
|
signatureResult.sessionNonces
|
|
@@ -1051,7 +1153,6 @@ var ZyfaiSDK = class {
|
|
|
1051
1153
|
});
|
|
1052
1154
|
return {
|
|
1053
1155
|
success: true,
|
|
1054
|
-
sessionKeyAddress: safeAddress,
|
|
1055
1156
|
signature,
|
|
1056
1157
|
sessionNonces
|
|
1057
1158
|
};
|
|
@@ -1061,6 +1162,30 @@ var ZyfaiSDK = class {
|
|
|
1061
1162
|
);
|
|
1062
1163
|
}
|
|
1063
1164
|
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Update user protocols with available protocols from the chain
|
|
1167
|
+
* This method is automatically called before activating session key
|
|
1168
|
+
*
|
|
1169
|
+
* @param chainId - Target chain ID
|
|
1170
|
+
* @internal
|
|
1171
|
+
*/
|
|
1172
|
+
async updateUserProtocols(chainId) {
|
|
1173
|
+
try {
|
|
1174
|
+
const protocolsResponse = await this.getAvailableProtocols(chainId);
|
|
1175
|
+
if (!protocolsResponse.protocols || protocolsResponse.protocols.length === 0) {
|
|
1176
|
+
console.warn(`No protocols available for chain ${chainId}`);
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
const protocolIds = protocolsResponse.protocols.map((p) => p.id);
|
|
1180
|
+
await this.updateUserProfile({
|
|
1181
|
+
protocols: protocolIds
|
|
1182
|
+
});
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
console.warn(
|
|
1185
|
+
`Failed to update user protocols: ${error.message}`
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1064
1189
|
/**
|
|
1065
1190
|
* Activate session key via ZyFAI API
|
|
1066
1191
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zyfai/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "TypeScript SDK for ZyFAI Yield Optimization Engine - Deploy Safe smart wallets, manage session keys, and interact with DeFi protocols",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -28,7 +28,13 @@
|
|
|
28
28
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
29
29
|
"lint": "eslint src --ext .ts",
|
|
30
30
|
"test": "jest",
|
|
31
|
-
"prepublishOnly": "npm run build"
|
|
31
|
+
"prepublishOnly": "npm run build",
|
|
32
|
+
"docs": "typedoc",
|
|
33
|
+
"docs:watch": "typedoc --watch",
|
|
34
|
+
"docs:json": "typedoc --json docs/api.json",
|
|
35
|
+
"docs:dev": "cd website && pnpm start",
|
|
36
|
+
"docs:build": "pnpm docs && cd website && pnpm build",
|
|
37
|
+
"docs:serve": "cd website && pnpm serve"
|
|
32
38
|
},
|
|
33
39
|
"keywords": [
|
|
34
40
|
"zyfai",
|
|
@@ -70,6 +76,8 @@
|
|
|
70
76
|
"@types/node": "^20.0.0",
|
|
71
77
|
"dotenv": "^17.2.3",
|
|
72
78
|
"tsup": "^8.0.0",
|
|
79
|
+
"typedoc": "^0.28.15",
|
|
80
|
+
"typedoc-plugin-markdown": "^4.9.0",
|
|
73
81
|
"typescript": "^5.3.0"
|
|
74
82
|
},
|
|
75
83
|
"peerDependencies": {
|