@karn_lat/protocol-sdk 0.1.0-alpha.4 → 0.1.0-alpha.5
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/wallet/adapters/FreighterAdapter.d.ts +3 -23
- package/dist/wallet/adapters/FreighterAdapter.d.ts.map +1 -1
- package/dist/wallet/adapters/FreighterAdapter.js +63 -22
- package/dist/wallet/adapters/FreighterAdapter.js.map +1 -1
- package/package.json +2 -2
- package/src/wallet/adapters/FreighterAdapter.ts +72 -52
|
@@ -5,31 +5,12 @@
|
|
|
5
5
|
* https://freighter.app
|
|
6
6
|
*/
|
|
7
7
|
import { WalletAdapter, WalletType, WalletMetadata, SignTransactionOptions } from '../types.js';
|
|
8
|
-
interface FreighterAPI {
|
|
9
|
-
isConnected(): Promise<boolean>;
|
|
10
|
-
getPublicKey(): Promise<string>;
|
|
11
|
-
signTransaction(xdr: string, opts?: {
|
|
12
|
-
network?: string;
|
|
13
|
-
networkPassphrase?: string;
|
|
14
|
-
accountToSign?: string;
|
|
15
|
-
}): Promise<string>;
|
|
16
|
-
getNetwork(): Promise<string>;
|
|
17
|
-
getNetworkDetails(): Promise<{
|
|
18
|
-
network: string;
|
|
19
|
-
networkPassphrase: string;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
declare global {
|
|
23
|
-
interface Window {
|
|
24
|
-
freighter?: FreighterAPI;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
8
|
export declare class FreighterAdapter implements WalletAdapter {
|
|
28
9
|
type: WalletType;
|
|
29
10
|
metadata: WalletMetadata;
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
private
|
|
11
|
+
private freighter;
|
|
12
|
+
private canUseBrowserFreighterApi;
|
|
13
|
+
private loadFreighter;
|
|
33
14
|
isAvailable(): Promise<boolean>;
|
|
34
15
|
connect(): Promise<string>;
|
|
35
16
|
disconnect(): Promise<void>;
|
|
@@ -38,5 +19,4 @@ export declare class FreighterAdapter implements WalletAdapter {
|
|
|
38
19
|
signTransaction(xdr: string, options?: SignTransactionOptions): Promise<string>;
|
|
39
20
|
getNetwork(): Promise<string>;
|
|
40
21
|
}
|
|
41
|
-
export {};
|
|
42
22
|
//# sourceMappingURL=FreighterAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FreighterAdapter.d.ts","sourceRoot":"","sources":["../../../src/wallet/adapters/FreighterAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,sBAAsB,EAGvB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"FreighterAdapter.d.ts","sourceRoot":"","sources":["../../../src/wallet/adapters/FreighterAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,sBAAsB,EAGvB,MAAM,aAAa,CAAC;AAarB,qBAAa,gBAAiB,YAAW,aAAa;IACpD,IAAI,aAAwB;IAE5B,QAAQ,EAAE,cAAc,CAQtB;IAEF,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,CAAC,yBAAyB;YAUnB,aAAa;IA0BrB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAa/B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IA2B1B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcpC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAU/B,eAAe,CACnB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,MAAM,CAAC;IA8BZ,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;CAgBpC"}
|
|
@@ -17,24 +17,60 @@ export class FreighterAdapter {
|
|
|
17
17
|
description: 'Official Stellar wallet extension with Soroban support',
|
|
18
18
|
isAvailable: false,
|
|
19
19
|
};
|
|
20
|
-
this.
|
|
21
|
-
this.init();
|
|
20
|
+
this.freighter = null;
|
|
22
21
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
canUseBrowserFreighterApi() {
|
|
23
|
+
// In Node/Jest we may have `global.window` mocked but without real browser globals.
|
|
24
|
+
// `@stellar/freighter-api` touches `window.location.origin` at import time.
|
|
25
|
+
return (typeof window !== 'undefined' &&
|
|
26
|
+
typeof window.location?.origin === 'string' &&
|
|
27
|
+
typeof document !== 'undefined');
|
|
28
|
+
}
|
|
29
|
+
async loadFreighter() {
|
|
30
|
+
if (this.freighter)
|
|
31
|
+
return this.freighter;
|
|
32
|
+
// 1) Prefer legacy window injection if present (also used by our Jest tests).
|
|
33
|
+
if (typeof window !== 'undefined') {
|
|
34
|
+
const injected = window.freighter;
|
|
35
|
+
if (injected) {
|
|
36
|
+
this.freighter = injected;
|
|
37
|
+
return injected;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// 2) In real browsers, use the official module API.
|
|
41
|
+
if (!this.canUseBrowserFreighterApi()) {
|
|
42
|
+
throw new WalletError('Freighter is not installed', WalletErrorCode.NOT_INSTALLED, WalletType.FREIGHTER);
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const mod = (await import('@stellar/freighter-api'));
|
|
46
|
+
this.freighter = mod;
|
|
47
|
+
return mod;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
throw new WalletError('Freighter is not installed', WalletErrorCode.NOT_INSTALLED, WalletType.FREIGHTER);
|
|
27
51
|
}
|
|
28
52
|
}
|
|
29
53
|
async isAvailable() {
|
|
30
|
-
|
|
54
|
+
try {
|
|
55
|
+
const freighter = await this.loadFreighter();
|
|
56
|
+
if (typeof freighter.isConnected !== 'function')
|
|
57
|
+
return false;
|
|
58
|
+
await freighter.isConnected();
|
|
59
|
+
this.metadata.isAvailable = true;
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
this.metadata.isAvailable = false;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
31
66
|
}
|
|
32
67
|
async connect() {
|
|
33
|
-
|
|
34
|
-
|
|
68
|
+
const freighter = await this.loadFreighter();
|
|
69
|
+
if (typeof freighter.getPublicKey !== 'function') {
|
|
70
|
+
throw new WalletError('Freighter API is unavailable', WalletErrorCode.NOT_INSTALLED, WalletType.FREIGHTER);
|
|
35
71
|
}
|
|
36
72
|
try {
|
|
37
|
-
const publicKey = await
|
|
73
|
+
const publicKey = await freighter.getPublicKey();
|
|
38
74
|
if (!publicKey) {
|
|
39
75
|
throw new WalletError('User rejected connection request', WalletErrorCode.USER_REJECTED, WalletType.FREIGHTER);
|
|
40
76
|
}
|
|
@@ -49,37 +85,41 @@ export class FreighterAdapter {
|
|
|
49
85
|
async disconnect() {
|
|
50
86
|
// Freighter doesn't have explicit disconnect
|
|
51
87
|
// Connection state is managed by extension
|
|
52
|
-
|
|
88
|
+
// Keep module cached, just mark unavailable until next check.
|
|
89
|
+
this.metadata.isAvailable = false;
|
|
53
90
|
}
|
|
54
91
|
async getAddress() {
|
|
55
|
-
if (!this.api)
|
|
56
|
-
return null;
|
|
57
92
|
try {
|
|
58
|
-
const
|
|
93
|
+
const freighter = await this.loadFreighter();
|
|
94
|
+
if (typeof freighter.isConnected !== 'function' || typeof freighter.getPublicKey !== 'function')
|
|
95
|
+
return null;
|
|
96
|
+
const connected = await freighter.isConnected();
|
|
59
97
|
if (!connected)
|
|
60
98
|
return null;
|
|
61
|
-
return await
|
|
99
|
+
return await freighter.getPublicKey();
|
|
62
100
|
}
|
|
63
101
|
catch {
|
|
64
102
|
return null;
|
|
65
103
|
}
|
|
66
104
|
}
|
|
67
105
|
async isConnected() {
|
|
68
|
-
if (!this.api)
|
|
69
|
-
return false;
|
|
70
106
|
try {
|
|
71
|
-
|
|
107
|
+
const freighter = await this.loadFreighter();
|
|
108
|
+
if (typeof freighter.isConnected !== 'function')
|
|
109
|
+
return false;
|
|
110
|
+
return await freighter.isConnected();
|
|
72
111
|
}
|
|
73
112
|
catch {
|
|
74
113
|
return false;
|
|
75
114
|
}
|
|
76
115
|
}
|
|
77
116
|
async signTransaction(xdr, options) {
|
|
78
|
-
|
|
117
|
+
const freighter = await this.loadFreighter();
|
|
118
|
+
if (typeof freighter.signTransaction !== 'function') {
|
|
79
119
|
throw new WalletError('Freighter is not connected', WalletErrorCode.NOT_CONNECTED, WalletType.FREIGHTER);
|
|
80
120
|
}
|
|
81
121
|
try {
|
|
82
|
-
const signedXdr = await
|
|
122
|
+
const signedXdr = await freighter.signTransaction(xdr, {
|
|
83
123
|
networkPassphrase: options?.networkPassphrase,
|
|
84
124
|
accountToSign: options?.accountToSign,
|
|
85
125
|
});
|
|
@@ -93,11 +133,12 @@ export class FreighterAdapter {
|
|
|
93
133
|
}
|
|
94
134
|
}
|
|
95
135
|
async getNetwork() {
|
|
96
|
-
|
|
136
|
+
const freighter = await this.loadFreighter();
|
|
137
|
+
if (typeof freighter.getNetwork !== 'function') {
|
|
97
138
|
throw new WalletError('Freighter is not connected', WalletErrorCode.NOT_CONNECTED, WalletType.FREIGHTER);
|
|
98
139
|
}
|
|
99
140
|
try {
|
|
100
|
-
return await
|
|
141
|
+
return await freighter.getNetwork();
|
|
101
142
|
}
|
|
102
143
|
catch (error) {
|
|
103
144
|
throw new WalletError(`Failed to get network: ${error.message}`, WalletErrorCode.NETWORK_ERROR, WalletType.FREIGHTER);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FreighterAdapter.js","sourceRoot":"","sources":["../../../src/wallet/adapters/FreighterAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,UAAU,EAGV,WAAW,EACX,eAAe,GAChB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"FreighterAdapter.js","sourceRoot":"","sources":["../../../src/wallet/adapters/FreighterAdapter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@karn_lat/protocol-sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.5",
|
|
4
4
|
"description": "Official TypeScript SDK for Karn Protocol - Contribution-driven governance on Stellar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"bugs": {
|
|
72
72
|
"url": "https://github.com/ThaisFReis/karn-protocol/issues"
|
|
73
73
|
},
|
|
74
|
-
"homepage": "https://
|
|
74
|
+
"homepage": "https://karn-protocol.vercel.app/"
|
|
75
75
|
}
|
|
@@ -14,23 +14,16 @@ import {
|
|
|
14
14
|
WalletErrorCode,
|
|
15
15
|
} from '../types.js';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
signTransaction(
|
|
17
|
+
type FreighterModule = {
|
|
18
|
+
isConnected?: () => Promise<boolean>;
|
|
19
|
+
getPublicKey?: () => Promise<string>;
|
|
20
|
+
signTransaction?: (
|
|
22
21
|
xdr: string,
|
|
23
22
|
opts?: { network?: string; networkPassphrase?: string; accountToSign?: string }
|
|
24
|
-
)
|
|
25
|
-
getNetwork()
|
|
26
|
-
getNetworkDetails()
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
declare global {
|
|
30
|
-
interface Window {
|
|
31
|
-
freighter?: FreighterAPI;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
23
|
+
) => Promise<string>;
|
|
24
|
+
getNetwork?: () => Promise<string>;
|
|
25
|
+
getNetworkDetails?: () => Promise<{ network: string; networkPassphrase: string }>;
|
|
26
|
+
};
|
|
34
27
|
|
|
35
28
|
export class FreighterAdapter implements WalletAdapter {
|
|
36
29
|
type = WalletType.FREIGHTER;
|
|
@@ -45,34 +38,65 @@ export class FreighterAdapter implements WalletAdapter {
|
|
|
45
38
|
isAvailable: false,
|
|
46
39
|
};
|
|
47
40
|
|
|
48
|
-
private
|
|
41
|
+
private freighter: FreighterModule | null = null;
|
|
49
42
|
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
private canUseBrowserFreighterApi(): boolean {
|
|
44
|
+
// In Node/Jest we may have `global.window` mocked but without real browser globals.
|
|
45
|
+
// `@stellar/freighter-api` touches `window.location.origin` at import time.
|
|
46
|
+
return (
|
|
47
|
+
typeof window !== 'undefined' &&
|
|
48
|
+
typeof (window as any).location?.origin === 'string' &&
|
|
49
|
+
typeof document !== 'undefined'
|
|
50
|
+
);
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
private
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
private async loadFreighter(): Promise<FreighterModule> {
|
|
54
|
+
if (this.freighter) return this.freighter;
|
|
55
|
+
|
|
56
|
+
// 1) Prefer legacy window injection if present (also used by our Jest tests).
|
|
57
|
+
if (typeof window !== 'undefined') {
|
|
58
|
+
const injected = (window as any).freighter as FreighterModule | undefined;
|
|
59
|
+
if (injected) {
|
|
60
|
+
this.freighter = injected;
|
|
61
|
+
return injected;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 2) In real browsers, use the official module API.
|
|
66
|
+
if (!this.canUseBrowserFreighterApi()) {
|
|
67
|
+
throw new WalletError('Freighter is not installed', WalletErrorCode.NOT_INSTALLED, WalletType.FREIGHTER);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const mod = (await import('@stellar/freighter-api')) as unknown as FreighterModule;
|
|
72
|
+
this.freighter = mod;
|
|
73
|
+
return mod;
|
|
74
|
+
} catch {
|
|
75
|
+
throw new WalletError('Freighter is not installed', WalletErrorCode.NOT_INSTALLED, WalletType.FREIGHTER);
|
|
58
76
|
}
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
async isAvailable(): Promise<boolean> {
|
|
62
|
-
|
|
80
|
+
try {
|
|
81
|
+
const freighter = await this.loadFreighter();
|
|
82
|
+
if (typeof freighter.isConnected !== 'function') return false;
|
|
83
|
+
await freighter.isConnected();
|
|
84
|
+
this.metadata.isAvailable = true;
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
this.metadata.isAvailable = false;
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
63
90
|
}
|
|
64
91
|
|
|
65
92
|
async connect(): Promise<string> {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
WalletErrorCode.NOT_INSTALLED,
|
|
70
|
-
WalletType.FREIGHTER
|
|
71
|
-
);
|
|
93
|
+
const freighter = await this.loadFreighter();
|
|
94
|
+
if (typeof freighter.getPublicKey !== 'function') {
|
|
95
|
+
throw new WalletError('Freighter API is unavailable', WalletErrorCode.NOT_INSTALLED, WalletType.FREIGHTER);
|
|
72
96
|
}
|
|
73
97
|
|
|
74
98
|
try {
|
|
75
|
-
const publicKey = await
|
|
99
|
+
const publicKey = await freighter.getPublicKey();
|
|
76
100
|
if (!publicKey) {
|
|
77
101
|
throw new WalletError(
|
|
78
102
|
'User rejected connection request',
|
|
@@ -95,27 +119,29 @@ export class FreighterAdapter implements WalletAdapter {
|
|
|
95
119
|
async disconnect(): Promise<void> {
|
|
96
120
|
// Freighter doesn't have explicit disconnect
|
|
97
121
|
// Connection state is managed by extension
|
|
98
|
-
|
|
122
|
+
// Keep module cached, just mark unavailable until next check.
|
|
123
|
+
this.metadata.isAvailable = false;
|
|
99
124
|
}
|
|
100
125
|
|
|
101
126
|
async getAddress(): Promise<string | null> {
|
|
102
|
-
if (!this.api) return null;
|
|
103
|
-
|
|
104
127
|
try {
|
|
105
|
-
const
|
|
128
|
+
const freighter = await this.loadFreighter();
|
|
129
|
+
if (typeof freighter.isConnected !== 'function' || typeof freighter.getPublicKey !== 'function') return null;
|
|
130
|
+
|
|
131
|
+
const connected = await freighter.isConnected();
|
|
106
132
|
if (!connected) return null;
|
|
107
133
|
|
|
108
|
-
return await
|
|
134
|
+
return await freighter.getPublicKey();
|
|
109
135
|
} catch {
|
|
110
136
|
return null;
|
|
111
137
|
}
|
|
112
138
|
}
|
|
113
139
|
|
|
114
140
|
async isConnected(): Promise<boolean> {
|
|
115
|
-
if (!this.api) return false;
|
|
116
|
-
|
|
117
141
|
try {
|
|
118
|
-
|
|
142
|
+
const freighter = await this.loadFreighter();
|
|
143
|
+
if (typeof freighter.isConnected !== 'function') return false;
|
|
144
|
+
return await freighter.isConnected();
|
|
119
145
|
} catch {
|
|
120
146
|
return false;
|
|
121
147
|
}
|
|
@@ -125,16 +151,13 @@ export class FreighterAdapter implements WalletAdapter {
|
|
|
125
151
|
xdr: string,
|
|
126
152
|
options?: SignTransactionOptions
|
|
127
153
|
): Promise<string> {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
WalletErrorCode.NOT_CONNECTED,
|
|
132
|
-
WalletType.FREIGHTER
|
|
133
|
-
);
|
|
154
|
+
const freighter = await this.loadFreighter();
|
|
155
|
+
if (typeof freighter.signTransaction !== 'function') {
|
|
156
|
+
throw new WalletError('Freighter is not connected', WalletErrorCode.NOT_CONNECTED, WalletType.FREIGHTER);
|
|
134
157
|
}
|
|
135
158
|
|
|
136
159
|
try {
|
|
137
|
-
const signedXdr = await
|
|
160
|
+
const signedXdr = await freighter.signTransaction(xdr, {
|
|
138
161
|
networkPassphrase: options?.networkPassphrase,
|
|
139
162
|
accountToSign: options?.accountToSign,
|
|
140
163
|
});
|
|
@@ -158,16 +181,13 @@ export class FreighterAdapter implements WalletAdapter {
|
|
|
158
181
|
}
|
|
159
182
|
|
|
160
183
|
async getNetwork(): Promise<string> {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
WalletErrorCode.NOT_CONNECTED,
|
|
165
|
-
WalletType.FREIGHTER
|
|
166
|
-
);
|
|
184
|
+
const freighter = await this.loadFreighter();
|
|
185
|
+
if (typeof freighter.getNetwork !== 'function') {
|
|
186
|
+
throw new WalletError('Freighter is not connected', WalletErrorCode.NOT_CONNECTED, WalletType.FREIGHTER);
|
|
167
187
|
}
|
|
168
188
|
|
|
169
189
|
try {
|
|
170
|
-
return await
|
|
190
|
+
return await freighter.getNetwork();
|
|
171
191
|
} catch (error: any) {
|
|
172
192
|
throw new WalletError(
|
|
173
193
|
`Failed to get network: ${error.message}`,
|