wallet-adapter-gameshift 0.1.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/lib/cjs/adapter.js +301 -0
- package/lib/cjs/adapter.js.map +1 -0
- package/lib/cjs/index.js +18 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/package.json +1 -0
- package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/lib/esm/adapter.js +273 -0
- package/lib/esm/adapter.js.map +1 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/tsconfig.esm.tsbuildinfo +1 -0
- package/lib/types/adapter.d.ts +54 -0
- package/lib/types/adapter.d.ts.map +1 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.d.ts.map +1 -0
- package/package.json +45 -0
- package/src/adapter.ts +384 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.GameshiftWalletAdapter = exports.GameshiftWalletName = void 0;
|
|
13
|
+
const wallet_adapter_base_1 = require("@solana/wallet-adapter-base");
|
|
14
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
15
|
+
const metakeep_1 = require("metakeep");
|
|
16
|
+
exports.GameshiftWalletName = 'Gameshift';
|
|
17
|
+
class GameshiftWalletAdapter extends wallet_adapter_base_1.BaseMessageSignerWalletAdapter {
|
|
18
|
+
constructor(config) {
|
|
19
|
+
super();
|
|
20
|
+
this.name = exports.GameshiftWalletName;
|
|
21
|
+
this.url = 'https://gameshift.build';
|
|
22
|
+
this.icon = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiM2QjQ2QzEiLz4KPHBhdGggZD0iTTMwIDU0QzMwIDQwLjc0NTIgNDAuNzQ1MiAzMCA1NCAzMEM2Ny4yNTQ4IDMwIDc4IDQwLjc0NTIgNzggNTRDNzggNjcuMjU0OCA2Ny4yNTQ4IDc4IDU0IDc4QzQwLjc0NTIgNzggMzAgNjcuMjU0OCAzMCA1NFoiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNiIvPgo8cGF0aCBkPSJNNTQgNDJWNjZNNDIgNTRINjYiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPg==';
|
|
23
|
+
this.supportedTransactionVersions = new Set(['legacy', 0]);
|
|
24
|
+
this._readyState = typeof window === 'undefined' || typeof document === 'undefined'
|
|
25
|
+
? wallet_adapter_base_1.WalletReadyState.Unsupported
|
|
26
|
+
: wallet_adapter_base_1.WalletReadyState.Loadable;
|
|
27
|
+
this._connecting = false;
|
|
28
|
+
this._publicKey = null;
|
|
29
|
+
this._token = null;
|
|
30
|
+
this._email = null;
|
|
31
|
+
this._portalUrl = config.portalUrl || 'http://localhost:3000';
|
|
32
|
+
this._metakeepAppId = config.metakeepAppId;
|
|
33
|
+
this._popupWidth = config.popupWidth || 450;
|
|
34
|
+
this._popupHeight = config.popupHeight || 650;
|
|
35
|
+
this._popup = null;
|
|
36
|
+
this._messageHandler = null;
|
|
37
|
+
this._popupCheckInterval = null;
|
|
38
|
+
}
|
|
39
|
+
get publicKey() {
|
|
40
|
+
return this._publicKey;
|
|
41
|
+
}
|
|
42
|
+
get connecting() {
|
|
43
|
+
return this._connecting;
|
|
44
|
+
}
|
|
45
|
+
get readyState() {
|
|
46
|
+
return this._readyState;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the authentication token received from the GameShift portal.
|
|
50
|
+
* This can be used for server-side token exchange.
|
|
51
|
+
*/
|
|
52
|
+
get token() {
|
|
53
|
+
return this._token;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the user's email address after connection.
|
|
57
|
+
*/
|
|
58
|
+
get email() {
|
|
59
|
+
return this._email;
|
|
60
|
+
}
|
|
61
|
+
connect() {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
var _a;
|
|
64
|
+
try {
|
|
65
|
+
if (this.connected || this.connecting)
|
|
66
|
+
return;
|
|
67
|
+
if (this._readyState === wallet_adapter_base_1.WalletReadyState.Unsupported) {
|
|
68
|
+
throw new wallet_adapter_base_1.WalletConnectionError('Wallet is not supported in this environment');
|
|
69
|
+
}
|
|
70
|
+
this._connecting = true;
|
|
71
|
+
const connectionPromise = new Promise((resolve, reject) => {
|
|
72
|
+
const state = `gameshift-${Date.now()}`;
|
|
73
|
+
let isResolved = false;
|
|
74
|
+
// Calculate popup position (centered)
|
|
75
|
+
const left = window.screenX + (window.outerWidth - this._popupWidth) / 2;
|
|
76
|
+
const top = window.screenY + (window.outerHeight - this._popupHeight) / 2;
|
|
77
|
+
// Build popup URL
|
|
78
|
+
const origin = window.location.origin;
|
|
79
|
+
const popupUrl = `${this._portalUrl}/auth/wallet-connect?origin=${encodeURIComponent(origin)}&state=${encodeURIComponent(state)}`;
|
|
80
|
+
// Message handler for postMessage from popup
|
|
81
|
+
this._messageHandler = (event) => {
|
|
82
|
+
var _a;
|
|
83
|
+
// Only accept messages from the portal
|
|
84
|
+
if (event.origin !== this._portalUrl)
|
|
85
|
+
return;
|
|
86
|
+
const message = event.data;
|
|
87
|
+
switch (message.type) {
|
|
88
|
+
case 'gameshift:auth:success':
|
|
89
|
+
if (message.data && !isResolved) {
|
|
90
|
+
isResolved = true;
|
|
91
|
+
this._cleanup();
|
|
92
|
+
resolve({
|
|
93
|
+
publicKey: message.data.publicKey,
|
|
94
|
+
token: message.data.token,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case 'gameshift:auth:error':
|
|
99
|
+
if (!isResolved) {
|
|
100
|
+
isResolved = true;
|
|
101
|
+
this._cleanup();
|
|
102
|
+
reject(new wallet_adapter_base_1.WalletConnectionError(((_a = message.error) === null || _a === void 0 ? void 0 : _a.message) || 'Authentication failed'));
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
case 'gameshift:auth:closed':
|
|
106
|
+
// Ignore - during OAuth flows the portal may send this incorrectly.
|
|
107
|
+
// The connection will remain in "connecting" state if user closes popup manually.
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
window.addEventListener('message', this._messageHandler);
|
|
112
|
+
// Open popup
|
|
113
|
+
this._popup = window.open(popupUrl, 'gameshift-wallet-connect', `width=${this._popupWidth},height=${this._popupHeight},left=${left},top=${top},popup=1,scrollbars=yes`);
|
|
114
|
+
if (!this._popup) {
|
|
115
|
+
this._cleanup();
|
|
116
|
+
reject(new wallet_adapter_base_1.WalletConnectionError('Failed to open popup - it may be blocked by the browser'));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Poll for popup being closed by user
|
|
120
|
+
// Use a counter to allow OAuth redirects time to complete
|
|
121
|
+
let closedCheckCount = 0;
|
|
122
|
+
this._popupCheckInterval = setInterval(() => {
|
|
123
|
+
var _a;
|
|
124
|
+
try {
|
|
125
|
+
if ((_a = this._popup) === null || _a === void 0 ? void 0 : _a.closed) {
|
|
126
|
+
closedCheckCount++;
|
|
127
|
+
// Wait for 3 consecutive checks (1.5s) to confirm it's really closed
|
|
128
|
+
// This allows OAuth redirects time to complete
|
|
129
|
+
if (closedCheckCount >= 3 && !isResolved) {
|
|
130
|
+
isResolved = true;
|
|
131
|
+
this._cleanup();
|
|
132
|
+
reject(new wallet_adapter_base_1.WalletConnectionError('User closed the authentication popup'));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
closedCheckCount = 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (_b) {
|
|
140
|
+
// Ignore errors accessing cross-origin popup
|
|
141
|
+
}
|
|
142
|
+
}, 500);
|
|
143
|
+
});
|
|
144
|
+
const { publicKey, token } = yield connectionPromise;
|
|
145
|
+
let parsedPublicKey;
|
|
146
|
+
try {
|
|
147
|
+
parsedPublicKey = new web3_js_1.PublicKey(publicKey);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
throw new wallet_adapter_base_1.WalletPublicKeyError(error === null || error === void 0 ? void 0 : error.message, error);
|
|
151
|
+
}
|
|
152
|
+
this._publicKey = parsedPublicKey;
|
|
153
|
+
this._token = token;
|
|
154
|
+
// Exchange token for user info (email)
|
|
155
|
+
try {
|
|
156
|
+
const response = yield fetch(`${this._portalUrl}/api/auth/wallet/exchange`, {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: {
|
|
159
|
+
'Content-Type': 'application/json',
|
|
160
|
+
},
|
|
161
|
+
body: JSON.stringify({ token }),
|
|
162
|
+
});
|
|
163
|
+
if (response.ok) {
|
|
164
|
+
const data = yield response.json();
|
|
165
|
+
this._email = ((_a = data.user) === null || _a === void 0 ? void 0 : _a.email) || null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (_b) {
|
|
169
|
+
// Silently fail - email is optional for connection
|
|
170
|
+
}
|
|
171
|
+
this.emit('connect', parsedPublicKey);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
this.emit('error', error);
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
this._connecting = false;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
disconnect() {
|
|
183
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
184
|
+
this._cleanup();
|
|
185
|
+
const wasConnected = this._publicKey !== null;
|
|
186
|
+
this._publicKey = null;
|
|
187
|
+
this._token = null;
|
|
188
|
+
this._email = null;
|
|
189
|
+
if (wasConnected) {
|
|
190
|
+
this.emit('disconnect');
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
sendTransaction(transaction_1, connection_1) {
|
|
195
|
+
return __awaiter(this, arguments, void 0, function* (transaction, connection, options = {}) {
|
|
196
|
+
try {
|
|
197
|
+
if (!this._publicKey)
|
|
198
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError();
|
|
199
|
+
transaction = yield this.signTransaction(transaction);
|
|
200
|
+
return connection.sendRawTransaction(transaction.serialize(), options);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
this.emit('error', error);
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
signTransaction(transaction) {
|
|
209
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
try {
|
|
211
|
+
if (!this._publicKey)
|
|
212
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError();
|
|
213
|
+
if (!this._email)
|
|
214
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError('User email not available');
|
|
215
|
+
const sdk = new metakeep_1.MetaKeep({
|
|
216
|
+
appId: this._metakeepAppId,
|
|
217
|
+
user: { email: this._email },
|
|
218
|
+
});
|
|
219
|
+
const signature = yield sdk.signTransaction(transaction, 'Signing transaction using GameShift Wallet');
|
|
220
|
+
transaction.addSignature(this._publicKey, Buffer.from(signature.signature.slice(2), 'hex'));
|
|
221
|
+
return transaction;
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
this.emit('error', error);
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
signAllTransactions(transactions) {
|
|
230
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
231
|
+
try {
|
|
232
|
+
if (!this._publicKey)
|
|
233
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError();
|
|
234
|
+
if (!this._email)
|
|
235
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError('User email not available');
|
|
236
|
+
const sdk = new metakeep_1.MetaKeep({
|
|
237
|
+
appId: this._metakeepAppId,
|
|
238
|
+
user: { email: this._email },
|
|
239
|
+
});
|
|
240
|
+
const { signatures } = yield sdk.signTransactionMultiple(transactions.map((t) => ({
|
|
241
|
+
transactionObject: t,
|
|
242
|
+
reason: 'Signing transaction using GameShift Wallet',
|
|
243
|
+
})), 'Signing multiple transactions using GameShift Wallet');
|
|
244
|
+
// Sign transactions one by one
|
|
245
|
+
const signedTransactions = [];
|
|
246
|
+
for (const transaction of transactions) {
|
|
247
|
+
transaction.addSignature(this._publicKey, Buffer.from(signatures[signedTransactions.length].signature.slice(2), 'hex'));
|
|
248
|
+
signedTransactions.push(transaction);
|
|
249
|
+
}
|
|
250
|
+
return signedTransactions;
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
this.emit('error', error);
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
signMessage(message) {
|
|
259
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
260
|
+
try {
|
|
261
|
+
if (!this._publicKey)
|
|
262
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError();
|
|
263
|
+
if (!this._email)
|
|
264
|
+
throw new wallet_adapter_base_1.WalletNotConnectedError('User email not available');
|
|
265
|
+
const sdk = new metakeep_1.MetaKeep({
|
|
266
|
+
appId: this._metakeepAppId,
|
|
267
|
+
user: { email: this._email },
|
|
268
|
+
});
|
|
269
|
+
const { signature } = yield sdk.signMessage(Buffer.from(message).toString(), 'Signing message using GameShift Wallet');
|
|
270
|
+
return Buffer.from(signature.slice(2), 'hex');
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
this.emit('error', error);
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
_cleanup() {
|
|
279
|
+
if (this._messageHandler) {
|
|
280
|
+
window.removeEventListener('message', this._messageHandler);
|
|
281
|
+
this._messageHandler = null;
|
|
282
|
+
}
|
|
283
|
+
if (this._popupCheckInterval) {
|
|
284
|
+
clearInterval(this._popupCheckInterval);
|
|
285
|
+
this._popupCheckInterval = null;
|
|
286
|
+
}
|
|
287
|
+
if (this._popup) {
|
|
288
|
+
try {
|
|
289
|
+
if (!this._popup.closed) {
|
|
290
|
+
this._popup.close();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (_a) {
|
|
294
|
+
// Ignore errors when accessing cross-origin popup
|
|
295
|
+
}
|
|
296
|
+
this._popup = null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
exports.GameshiftWalletAdapter = GameshiftWalletAdapter;
|
|
301
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/lib/cjs/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./adapter.js"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "commonjs" }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../../src/adapter.ts","../../src/index.ts"],"version":"5.8.3"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { BaseMessageSignerWalletAdapter, WalletConnectionError, WalletNotConnectedError, WalletPublicKeyError, WalletReadyState, } from '@solana/wallet-adapter-base';
|
|
2
|
+
import { PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { MetaKeep } from 'metakeep';
|
|
4
|
+
export const GameshiftWalletName = 'Gameshift';
|
|
5
|
+
export class GameshiftWalletAdapter extends BaseMessageSignerWalletAdapter {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
super();
|
|
8
|
+
this.name = GameshiftWalletName;
|
|
9
|
+
this.url = 'https://gameshift.build';
|
|
10
|
+
this.icon = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiM2QjQ2QzEiLz4KPHBhdGggZD0iTTMwIDU0QzMwIDQwLjc0NTIgNDAuNzQ1MiAzMCA1NCAzMEM2Ny4yNTQ4IDMwIDc4IDQwLjc0NTIgNzggNTRDNzggNjcuMjU0OCA2Ny4yNTQ4IDc4IDU0IDc4QzQwLjc0NTIgNzggMzAgNjcuMjU0OCAzMCA1NFoiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNiIvPgo8cGF0aCBkPSJNNTQgNDJWNjZNNDIgNTRINjYiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPg==';
|
|
11
|
+
this.supportedTransactionVersions = new Set(['legacy', 0]);
|
|
12
|
+
this._readyState = typeof window === 'undefined' || typeof document === 'undefined'
|
|
13
|
+
? WalletReadyState.Unsupported
|
|
14
|
+
: WalletReadyState.Loadable;
|
|
15
|
+
this._connecting = false;
|
|
16
|
+
this._publicKey = null;
|
|
17
|
+
this._token = null;
|
|
18
|
+
this._email = null;
|
|
19
|
+
this._portalUrl = config.portalUrl || 'http://localhost:3000';
|
|
20
|
+
this._metakeepAppId = config.metakeepAppId;
|
|
21
|
+
this._popupWidth = config.popupWidth || 450;
|
|
22
|
+
this._popupHeight = config.popupHeight || 650;
|
|
23
|
+
this._popup = null;
|
|
24
|
+
this._messageHandler = null;
|
|
25
|
+
this._popupCheckInterval = null;
|
|
26
|
+
}
|
|
27
|
+
get publicKey() {
|
|
28
|
+
return this._publicKey;
|
|
29
|
+
}
|
|
30
|
+
get connecting() {
|
|
31
|
+
return this._connecting;
|
|
32
|
+
}
|
|
33
|
+
get readyState() {
|
|
34
|
+
return this._readyState;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get the authentication token received from the GameShift portal.
|
|
38
|
+
* This can be used for server-side token exchange.
|
|
39
|
+
*/
|
|
40
|
+
get token() {
|
|
41
|
+
return this._token;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the user's email address after connection.
|
|
45
|
+
*/
|
|
46
|
+
get email() {
|
|
47
|
+
return this._email;
|
|
48
|
+
}
|
|
49
|
+
async connect() {
|
|
50
|
+
try {
|
|
51
|
+
if (this.connected || this.connecting)
|
|
52
|
+
return;
|
|
53
|
+
if (this._readyState === WalletReadyState.Unsupported) {
|
|
54
|
+
throw new WalletConnectionError('Wallet is not supported in this environment');
|
|
55
|
+
}
|
|
56
|
+
this._connecting = true;
|
|
57
|
+
const connectionPromise = new Promise((resolve, reject) => {
|
|
58
|
+
const state = `gameshift-${Date.now()}`;
|
|
59
|
+
let isResolved = false;
|
|
60
|
+
// Calculate popup position (centered)
|
|
61
|
+
const left = window.screenX + (window.outerWidth - this._popupWidth) / 2;
|
|
62
|
+
const top = window.screenY + (window.outerHeight - this._popupHeight) / 2;
|
|
63
|
+
// Build popup URL
|
|
64
|
+
const origin = window.location.origin;
|
|
65
|
+
const popupUrl = `${this._portalUrl}/auth/wallet-connect?origin=${encodeURIComponent(origin)}&state=${encodeURIComponent(state)}`;
|
|
66
|
+
// Message handler for postMessage from popup
|
|
67
|
+
this._messageHandler = (event) => {
|
|
68
|
+
// Only accept messages from the portal
|
|
69
|
+
if (event.origin !== this._portalUrl)
|
|
70
|
+
return;
|
|
71
|
+
const message = event.data;
|
|
72
|
+
switch (message.type) {
|
|
73
|
+
case 'gameshift:auth:success':
|
|
74
|
+
if (message.data && !isResolved) {
|
|
75
|
+
isResolved = true;
|
|
76
|
+
this._cleanup();
|
|
77
|
+
resolve({
|
|
78
|
+
publicKey: message.data.publicKey,
|
|
79
|
+
token: message.data.token,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
case 'gameshift:auth:error':
|
|
84
|
+
if (!isResolved) {
|
|
85
|
+
isResolved = true;
|
|
86
|
+
this._cleanup();
|
|
87
|
+
reject(new WalletConnectionError(message.error?.message || 'Authentication failed'));
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
case 'gameshift:auth:closed':
|
|
91
|
+
// Ignore - during OAuth flows the portal may send this incorrectly.
|
|
92
|
+
// The connection will remain in "connecting" state if user closes popup manually.
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
window.addEventListener('message', this._messageHandler);
|
|
97
|
+
// Open popup
|
|
98
|
+
this._popup = window.open(popupUrl, 'gameshift-wallet-connect', `width=${this._popupWidth},height=${this._popupHeight},left=${left},top=${top},popup=1,scrollbars=yes`);
|
|
99
|
+
if (!this._popup) {
|
|
100
|
+
this._cleanup();
|
|
101
|
+
reject(new WalletConnectionError('Failed to open popup - it may be blocked by the browser'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Poll for popup being closed by user
|
|
105
|
+
// Use a counter to allow OAuth redirects time to complete
|
|
106
|
+
let closedCheckCount = 0;
|
|
107
|
+
this._popupCheckInterval = setInterval(() => {
|
|
108
|
+
try {
|
|
109
|
+
if (this._popup?.closed) {
|
|
110
|
+
closedCheckCount++;
|
|
111
|
+
// Wait for 3 consecutive checks (1.5s) to confirm it's really closed
|
|
112
|
+
// This allows OAuth redirects time to complete
|
|
113
|
+
if (closedCheckCount >= 3 && !isResolved) {
|
|
114
|
+
isResolved = true;
|
|
115
|
+
this._cleanup();
|
|
116
|
+
reject(new WalletConnectionError('User closed the authentication popup'));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
closedCheckCount = 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Ignore errors accessing cross-origin popup
|
|
125
|
+
}
|
|
126
|
+
}, 500);
|
|
127
|
+
});
|
|
128
|
+
const { publicKey, token } = await connectionPromise;
|
|
129
|
+
let parsedPublicKey;
|
|
130
|
+
try {
|
|
131
|
+
parsedPublicKey = new PublicKey(publicKey);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
throw new WalletPublicKeyError(error?.message, error);
|
|
135
|
+
}
|
|
136
|
+
this._publicKey = parsedPublicKey;
|
|
137
|
+
this._token = token;
|
|
138
|
+
// Exchange token for user info (email)
|
|
139
|
+
try {
|
|
140
|
+
const response = await fetch(`${this._portalUrl}/api/auth/wallet/exchange`, {
|
|
141
|
+
method: 'POST',
|
|
142
|
+
headers: {
|
|
143
|
+
'Content-Type': 'application/json',
|
|
144
|
+
},
|
|
145
|
+
body: JSON.stringify({ token }),
|
|
146
|
+
});
|
|
147
|
+
if (response.ok) {
|
|
148
|
+
const data = await response.json();
|
|
149
|
+
this._email = data.user?.email || null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Silently fail - email is optional for connection
|
|
154
|
+
}
|
|
155
|
+
this.emit('connect', parsedPublicKey);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.emit('error', error);
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
this._connecting = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async disconnect() {
|
|
166
|
+
this._cleanup();
|
|
167
|
+
const wasConnected = this._publicKey !== null;
|
|
168
|
+
this._publicKey = null;
|
|
169
|
+
this._token = null;
|
|
170
|
+
this._email = null;
|
|
171
|
+
if (wasConnected) {
|
|
172
|
+
this.emit('disconnect');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async sendTransaction(transaction, connection, options = {}) {
|
|
176
|
+
try {
|
|
177
|
+
if (!this._publicKey)
|
|
178
|
+
throw new WalletNotConnectedError();
|
|
179
|
+
transaction = await this.signTransaction(transaction);
|
|
180
|
+
return connection.sendRawTransaction(transaction.serialize(), options);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
this.emit('error', error);
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async signTransaction(transaction) {
|
|
188
|
+
try {
|
|
189
|
+
if (!this._publicKey)
|
|
190
|
+
throw new WalletNotConnectedError();
|
|
191
|
+
if (!this._email)
|
|
192
|
+
throw new WalletNotConnectedError('User email not available');
|
|
193
|
+
const sdk = new MetaKeep({
|
|
194
|
+
appId: this._metakeepAppId,
|
|
195
|
+
user: { email: this._email },
|
|
196
|
+
});
|
|
197
|
+
const signature = await sdk.signTransaction(transaction, 'Signing transaction using GameShift Wallet');
|
|
198
|
+
transaction.addSignature(this._publicKey, Buffer.from(signature.signature.slice(2), 'hex'));
|
|
199
|
+
return transaction;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
this.emit('error', error);
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async signAllTransactions(transactions) {
|
|
207
|
+
try {
|
|
208
|
+
if (!this._publicKey)
|
|
209
|
+
throw new WalletNotConnectedError();
|
|
210
|
+
if (!this._email)
|
|
211
|
+
throw new WalletNotConnectedError('User email not available');
|
|
212
|
+
const sdk = new MetaKeep({
|
|
213
|
+
appId: this._metakeepAppId,
|
|
214
|
+
user: { email: this._email },
|
|
215
|
+
});
|
|
216
|
+
const { signatures } = await sdk.signTransactionMultiple(transactions.map((t) => ({
|
|
217
|
+
transactionObject: t,
|
|
218
|
+
reason: 'Signing transaction using GameShift Wallet',
|
|
219
|
+
})), 'Signing multiple transactions using GameShift Wallet');
|
|
220
|
+
// Sign transactions one by one
|
|
221
|
+
const signedTransactions = [];
|
|
222
|
+
for (const transaction of transactions) {
|
|
223
|
+
transaction.addSignature(this._publicKey, Buffer.from(signatures[signedTransactions.length].signature.slice(2), 'hex'));
|
|
224
|
+
signedTransactions.push(transaction);
|
|
225
|
+
}
|
|
226
|
+
return signedTransactions;
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
this.emit('error', error);
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
async signMessage(message) {
|
|
234
|
+
try {
|
|
235
|
+
if (!this._publicKey)
|
|
236
|
+
throw new WalletNotConnectedError();
|
|
237
|
+
if (!this._email)
|
|
238
|
+
throw new WalletNotConnectedError('User email not available');
|
|
239
|
+
const sdk = new MetaKeep({
|
|
240
|
+
appId: this._metakeepAppId,
|
|
241
|
+
user: { email: this._email },
|
|
242
|
+
});
|
|
243
|
+
const { signature } = await sdk.signMessage(Buffer.from(message).toString(), 'Signing message using GameShift Wallet');
|
|
244
|
+
return Buffer.from(signature.slice(2), 'hex');
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
this.emit('error', error);
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
_cleanup() {
|
|
252
|
+
if (this._messageHandler) {
|
|
253
|
+
window.removeEventListener('message', this._messageHandler);
|
|
254
|
+
this._messageHandler = null;
|
|
255
|
+
}
|
|
256
|
+
if (this._popupCheckInterval) {
|
|
257
|
+
clearInterval(this._popupCheckInterval);
|
|
258
|
+
this._popupCheckInterval = null;
|
|
259
|
+
}
|
|
260
|
+
if (this._popup) {
|
|
261
|
+
try {
|
|
262
|
+
if (!this._popup.closed) {
|
|
263
|
+
this._popup.close();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Ignore errors when accessing cross-origin popup
|
|
268
|
+
}
|
|
269
|
+
this._popup = null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../../src/adapter.ts","../../src/index.ts"],"version":"5.8.3"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { SendTransactionOptions, WalletName } from '@solana/wallet-adapter-base';
|
|
2
|
+
import { BaseMessageSignerWalletAdapter, WalletReadyState } from '@solana/wallet-adapter-base';
|
|
3
|
+
import type { Connection, Transaction, TransactionSignature, TransactionVersion, VersionedTransaction } from '@solana/web3.js';
|
|
4
|
+
import { PublicKey } from '@solana/web3.js';
|
|
5
|
+
export interface GameshiftWalletAdapterConfig {
|
|
6
|
+
/** MetaKeep App ID for transaction signing (required) */
|
|
7
|
+
metakeepAppId: string;
|
|
8
|
+
/** The URL of the GameShift portal for wallet connection. Defaults to 'http://localhost:3000' */
|
|
9
|
+
portalUrl?: string;
|
|
10
|
+
/** Popup window width. Defaults to 450 */
|
|
11
|
+
popupWidth?: number;
|
|
12
|
+
/** Popup window height. Defaults to 650 */
|
|
13
|
+
popupHeight?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const GameshiftWalletName: WalletName<"Gameshift">;
|
|
16
|
+
export declare class GameshiftWalletAdapter extends BaseMessageSignerWalletAdapter {
|
|
17
|
+
name: WalletName<"Gameshift">;
|
|
18
|
+
url: string;
|
|
19
|
+
icon: string;
|
|
20
|
+
supportedTransactionVersions: ReadonlySet<TransactionVersion>;
|
|
21
|
+
private _connecting;
|
|
22
|
+
private _publicKey;
|
|
23
|
+
private _token;
|
|
24
|
+
private _email;
|
|
25
|
+
private _portalUrl;
|
|
26
|
+
private _metakeepAppId;
|
|
27
|
+
private _popupWidth;
|
|
28
|
+
private _popupHeight;
|
|
29
|
+
private _popup;
|
|
30
|
+
private _messageHandler;
|
|
31
|
+
private _popupCheckInterval;
|
|
32
|
+
private _readyState;
|
|
33
|
+
constructor(config: GameshiftWalletAdapterConfig);
|
|
34
|
+
get publicKey(): PublicKey | null;
|
|
35
|
+
get connecting(): boolean;
|
|
36
|
+
get readyState(): WalletReadyState;
|
|
37
|
+
/**
|
|
38
|
+
* Get the authentication token received from the GameShift portal.
|
|
39
|
+
* This can be used for server-side token exchange.
|
|
40
|
+
*/
|
|
41
|
+
get token(): string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Get the user's email address after connection.
|
|
44
|
+
*/
|
|
45
|
+
get email(): string | null;
|
|
46
|
+
connect(): Promise<void>;
|
|
47
|
+
disconnect(): Promise<void>;
|
|
48
|
+
sendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, connection: Connection, options?: SendTransactionOptions): Promise<TransactionSignature>;
|
|
49
|
+
signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
|
|
50
|
+
signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
|
|
51
|
+
signMessage(message: Uint8Array): Promise<Uint8Array>;
|
|
52
|
+
private _cleanup;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EACH,8BAA8B,EAI9B,gBAAgB,EACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACR,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,WAAW,4BAA4B;IACzC,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,mBAAmB,EAAkB,UAAU,CAAC,WAAW,CAAC,CAAC;AA4B1E,qBAAa,sBAAuB,SAAQ,8BAA8B;IACtE,IAAI,0BAAuB;IAC3B,GAAG,SAA6B;IAChC,IAAI,SACqkB;IACzkB,4BAA4B,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAA0B;IAEvF,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,mBAAmB,CAAwC;IACnE,OAAO,CAAC,WAAW,CAGiB;gBAExB,MAAM,EAAE,4BAA4B;IAehD,IAAI,SAAS,qBAEZ;IAED,IAAI,UAAU,YAEb;IAED,IAAI,UAAU,qBAEb;IAED;;;OAGG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoIxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAC9D,WAAW,EAAE,CAAC,EACd,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE,sBAA2B,GACrC,OAAO,CAAC,oBAAoB,CAAC;IAW1B,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAAE,WAAW,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBzF,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,oBAAoB,EAAE,YAAY,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAmClG,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAsB3D,OAAO,CAAC,QAAQ;CAsBnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wallet-adapter-gameshift",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "GameShift",
|
|
5
|
+
"repository": "https://github.com/anza-xyz/wallet-adapter",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"lib",
|
|
12
|
+
"src",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=20"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"main": "./lib/cjs/index.js",
|
|
21
|
+
"module": "./lib/esm/index.js",
|
|
22
|
+
"types": "./lib/types/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
"require": "./lib/cjs/index.js",
|
|
25
|
+
"import": "./lib/esm/index.js",
|
|
26
|
+
"types": "./lib/types/index.d.ts"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc --build --verbose && pnpm run package",
|
|
30
|
+
"clean": "shx mkdir -p lib && shx rm -rf lib",
|
|
31
|
+
"lint": "prettier --check 'src/{*,**/*}.{ts,tsx,js,jsx,json}' && eslint",
|
|
32
|
+
"package": "shx mkdir -p lib/cjs && shx echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@solana/web3.js": "^1.98.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@solana/wallet-adapter-base": "^0.9.27",
|
|
39
|
+
"metakeep": "^2.2.8"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@solana/web3.js": "^1.98.2",
|
|
43
|
+
"shx": "^0.4.0"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/adapter.ts
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import type { SendTransactionOptions, WalletName } from '@solana/wallet-adapter-base';
|
|
2
|
+
import {
|
|
3
|
+
BaseMessageSignerWalletAdapter,
|
|
4
|
+
WalletConnectionError,
|
|
5
|
+
WalletNotConnectedError,
|
|
6
|
+
WalletPublicKeyError,
|
|
7
|
+
WalletReadyState,
|
|
8
|
+
} from '@solana/wallet-adapter-base';
|
|
9
|
+
import type {
|
|
10
|
+
Connection,
|
|
11
|
+
Transaction,
|
|
12
|
+
TransactionSignature,
|
|
13
|
+
TransactionVersion,
|
|
14
|
+
VersionedTransaction,
|
|
15
|
+
} from '@solana/web3.js';
|
|
16
|
+
import { PublicKey } from '@solana/web3.js';
|
|
17
|
+
import { MetaKeep } from 'metakeep';
|
|
18
|
+
|
|
19
|
+
export interface GameshiftWalletAdapterConfig {
|
|
20
|
+
/** MetaKeep App ID for transaction signing (required) */
|
|
21
|
+
metakeepAppId: string;
|
|
22
|
+
/** The URL of the GameShift portal for wallet connection. Defaults to 'http://localhost:3000' */
|
|
23
|
+
portalUrl?: string;
|
|
24
|
+
/** Popup window width. Defaults to 450 */
|
|
25
|
+
popupWidth?: number;
|
|
26
|
+
/** Popup window height. Defaults to 650 */
|
|
27
|
+
popupHeight?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const GameshiftWalletName = 'Gameshift' as WalletName<'Gameshift'>;
|
|
31
|
+
|
|
32
|
+
interface GameshiftAuthSuccessData {
|
|
33
|
+
token: string;
|
|
34
|
+
publicKey: string;
|
|
35
|
+
state?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface GameshiftAuthMessage {
|
|
39
|
+
type: 'gameshift:auth:success' | 'gameshift:auth:error' | 'gameshift:auth:closed';
|
|
40
|
+
data?: GameshiftAuthSuccessData;
|
|
41
|
+
error?: {
|
|
42
|
+
code: string;
|
|
43
|
+
message: string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface GameshiftSignMessage {
|
|
48
|
+
type: 'gameshift:sign:success' | 'gameshift:sign:error' | 'gameshift:sign:closed';
|
|
49
|
+
data?: {
|
|
50
|
+
signedTransaction: string; // hex encoded signed transaction
|
|
51
|
+
};
|
|
52
|
+
error?: {
|
|
53
|
+
code: string;
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class GameshiftWalletAdapter extends BaseMessageSignerWalletAdapter {
|
|
59
|
+
name = GameshiftWalletName;
|
|
60
|
+
url = 'https://gameshift.build';
|
|
61
|
+
icon =
|
|
62
|
+
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiM2QjQ2QzEiLz4KPHBhdGggZD0iTTMwIDU0QzMwIDQwLjc0NTIgNDAuNzQ1MiAzMCA1NCAzMEM2Ny4yNTQ4IDMwIDc4IDQwLjc0NTIgNzggNTRDNzggNjcuMjU0OCA2Ny4yNTQ4IDc4IDU0IDc4QzQwLjc0NTIgNzggMzAgNjcuMjU0OCAzMCA1NFoiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNiIvPgo8cGF0aCBkPSJNNTQgNDJWNjZNNDIgNTRINjYiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPg==';
|
|
63
|
+
supportedTransactionVersions: ReadonlySet<TransactionVersion> = new Set(['legacy', 0]);
|
|
64
|
+
|
|
65
|
+
private _connecting: boolean;
|
|
66
|
+
private _publicKey: PublicKey | null;
|
|
67
|
+
private _token: string | null;
|
|
68
|
+
private _email: string | null;
|
|
69
|
+
private _portalUrl: string;
|
|
70
|
+
private _metakeepAppId: string;
|
|
71
|
+
private _popupWidth: number;
|
|
72
|
+
private _popupHeight: number;
|
|
73
|
+
private _popup: Window | null;
|
|
74
|
+
private _messageHandler: ((event: MessageEvent) => void) | null;
|
|
75
|
+
private _popupCheckInterval: ReturnType<typeof setInterval> | null;
|
|
76
|
+
private _readyState: WalletReadyState =
|
|
77
|
+
typeof window === 'undefined' || typeof document === 'undefined'
|
|
78
|
+
? WalletReadyState.Unsupported
|
|
79
|
+
: WalletReadyState.Loadable;
|
|
80
|
+
|
|
81
|
+
constructor(config: GameshiftWalletAdapterConfig) {
|
|
82
|
+
super();
|
|
83
|
+
this._connecting = false;
|
|
84
|
+
this._publicKey = null;
|
|
85
|
+
this._token = null;
|
|
86
|
+
this._email = null;
|
|
87
|
+
this._portalUrl = config.portalUrl || 'http://localhost:3000';
|
|
88
|
+
this._metakeepAppId = config.metakeepAppId;
|
|
89
|
+
this._popupWidth = config.popupWidth || 450;
|
|
90
|
+
this._popupHeight = config.popupHeight || 650;
|
|
91
|
+
this._popup = null;
|
|
92
|
+
this._messageHandler = null;
|
|
93
|
+
this._popupCheckInterval = null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get publicKey() {
|
|
97
|
+
return this._publicKey;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get connecting() {
|
|
101
|
+
return this._connecting;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get readyState() {
|
|
105
|
+
return this._readyState;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get the authentication token received from the GameShift portal.
|
|
110
|
+
* This can be used for server-side token exchange.
|
|
111
|
+
*/
|
|
112
|
+
get token(): string | null {
|
|
113
|
+
return this._token;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the user's email address after connection.
|
|
118
|
+
*/
|
|
119
|
+
get email(): string | null {
|
|
120
|
+
return this._email;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async connect(): Promise<void> {
|
|
124
|
+
try {
|
|
125
|
+
if (this.connected || this.connecting) return;
|
|
126
|
+
|
|
127
|
+
if (this._readyState === WalletReadyState.Unsupported) {
|
|
128
|
+
throw new WalletConnectionError('Wallet is not supported in this environment');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this._connecting = true;
|
|
132
|
+
|
|
133
|
+
const connectionPromise = new Promise<{ publicKey: string; token: string }>((resolve, reject) => {
|
|
134
|
+
const state = `gameshift-${Date.now()}`;
|
|
135
|
+
let isResolved = false;
|
|
136
|
+
|
|
137
|
+
// Calculate popup position (centered)
|
|
138
|
+
const left = window.screenX + (window.outerWidth - this._popupWidth) / 2;
|
|
139
|
+
const top = window.screenY + (window.outerHeight - this._popupHeight) / 2;
|
|
140
|
+
|
|
141
|
+
// Build popup URL
|
|
142
|
+
const origin = window.location.origin;
|
|
143
|
+
const popupUrl = `${this._portalUrl}/auth/wallet-connect?origin=${encodeURIComponent(origin)}&state=${encodeURIComponent(state)}`;
|
|
144
|
+
|
|
145
|
+
// Message handler for postMessage from popup
|
|
146
|
+
this._messageHandler = (event: MessageEvent) => {
|
|
147
|
+
// Only accept messages from the portal
|
|
148
|
+
if (event.origin !== this._portalUrl) return;
|
|
149
|
+
|
|
150
|
+
const message = event.data as GameshiftAuthMessage;
|
|
151
|
+
|
|
152
|
+
switch (message.type) {
|
|
153
|
+
case 'gameshift:auth:success':
|
|
154
|
+
if (message.data && !isResolved) {
|
|
155
|
+
isResolved = true;
|
|
156
|
+
this._cleanup();
|
|
157
|
+
resolve({
|
|
158
|
+
publicKey: message.data.publicKey,
|
|
159
|
+
token: message.data.token,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
|
|
164
|
+
case 'gameshift:auth:error':
|
|
165
|
+
if (!isResolved) {
|
|
166
|
+
isResolved = true;
|
|
167
|
+
this._cleanup();
|
|
168
|
+
reject(new WalletConnectionError(message.error?.message || 'Authentication failed'));
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
|
|
172
|
+
case 'gameshift:auth:closed':
|
|
173
|
+
// Ignore - during OAuth flows the portal may send this incorrectly.
|
|
174
|
+
// The connection will remain in "connecting" state if user closes popup manually.
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
window.addEventListener('message', this._messageHandler);
|
|
180
|
+
|
|
181
|
+
// Open popup
|
|
182
|
+
this._popup = window.open(
|
|
183
|
+
popupUrl,
|
|
184
|
+
'gameshift-wallet-connect',
|
|
185
|
+
`width=${this._popupWidth},height=${this._popupHeight},left=${left},top=${top},popup=1,scrollbars=yes`
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (!this._popup) {
|
|
189
|
+
this._cleanup();
|
|
190
|
+
reject(new WalletConnectionError('Failed to open popup - it may be blocked by the browser'));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Poll for popup being closed by user
|
|
195
|
+
// Use a counter to allow OAuth redirects time to complete
|
|
196
|
+
let closedCheckCount = 0;
|
|
197
|
+
this._popupCheckInterval = setInterval(() => {
|
|
198
|
+
try {
|
|
199
|
+
if (this._popup?.closed) {
|
|
200
|
+
closedCheckCount++;
|
|
201
|
+
// Wait for 3 consecutive checks (1.5s) to confirm it's really closed
|
|
202
|
+
// This allows OAuth redirects time to complete
|
|
203
|
+
if (closedCheckCount >= 3 && !isResolved) {
|
|
204
|
+
isResolved = true;
|
|
205
|
+
this._cleanup();
|
|
206
|
+
reject(new WalletConnectionError('User closed the authentication popup'));
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
closedCheckCount = 0;
|
|
210
|
+
}
|
|
211
|
+
} catch {
|
|
212
|
+
// Ignore errors accessing cross-origin popup
|
|
213
|
+
}
|
|
214
|
+
}, 500);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const { publicKey, token } = await connectionPromise;
|
|
218
|
+
|
|
219
|
+
let parsedPublicKey: PublicKey;
|
|
220
|
+
try {
|
|
221
|
+
parsedPublicKey = new PublicKey(publicKey);
|
|
222
|
+
} catch (error: any) {
|
|
223
|
+
throw new WalletPublicKeyError(error?.message, error);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
this._publicKey = parsedPublicKey;
|
|
227
|
+
this._token = token;
|
|
228
|
+
|
|
229
|
+
// Exchange token for user info (email)
|
|
230
|
+
try {
|
|
231
|
+
const response = await fetch(`${this._portalUrl}/api/auth/wallet/exchange`, {
|
|
232
|
+
method: 'POST',
|
|
233
|
+
headers: {
|
|
234
|
+
'Content-Type': 'application/json',
|
|
235
|
+
},
|
|
236
|
+
body: JSON.stringify({ token }),
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
if (response.ok) {
|
|
240
|
+
const data = await response.json();
|
|
241
|
+
this._email = data.user?.email || null;
|
|
242
|
+
}
|
|
243
|
+
} catch {
|
|
244
|
+
// Silently fail - email is optional for connection
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
this.emit('connect', parsedPublicKey);
|
|
248
|
+
} catch (error: any) {
|
|
249
|
+
this.emit('error', error);
|
|
250
|
+
throw error;
|
|
251
|
+
} finally {
|
|
252
|
+
this._connecting = false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async disconnect(): Promise<void> {
|
|
257
|
+
this._cleanup();
|
|
258
|
+
|
|
259
|
+
const wasConnected = this._publicKey !== null;
|
|
260
|
+
|
|
261
|
+
this._publicKey = null;
|
|
262
|
+
this._token = null;
|
|
263
|
+
this._email = null;
|
|
264
|
+
|
|
265
|
+
if (wasConnected) {
|
|
266
|
+
this.emit('disconnect');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async sendTransaction<T extends Transaction | VersionedTransaction>(
|
|
271
|
+
transaction: T,
|
|
272
|
+
connection: Connection,
|
|
273
|
+
options: SendTransactionOptions = {}
|
|
274
|
+
): Promise<TransactionSignature> {
|
|
275
|
+
try {
|
|
276
|
+
if (!this._publicKey) throw new WalletNotConnectedError();
|
|
277
|
+
transaction = await this.signTransaction(transaction);
|
|
278
|
+
return connection.sendRawTransaction(transaction.serialize(), options);
|
|
279
|
+
} catch (error: any) {
|
|
280
|
+
this.emit('error', error);
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T> {
|
|
286
|
+
try {
|
|
287
|
+
if (!this._publicKey) throw new WalletNotConnectedError();
|
|
288
|
+
if (!this._email) throw new WalletNotConnectedError('User email not available');
|
|
289
|
+
|
|
290
|
+
const sdk = new MetaKeep({
|
|
291
|
+
appId: this._metakeepAppId,
|
|
292
|
+
user: { email: this._email },
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const signature = await sdk.signTransaction(transaction, 'Signing transaction using GameShift Wallet');
|
|
296
|
+
transaction.addSignature(this._publicKey, Buffer.from(signature.signature.slice(2), 'hex'));
|
|
297
|
+
|
|
298
|
+
return transaction;
|
|
299
|
+
} catch (error: any) {
|
|
300
|
+
this.emit('error', error);
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]> {
|
|
306
|
+
try {
|
|
307
|
+
if (!this._publicKey) throw new WalletNotConnectedError();
|
|
308
|
+
if (!this._email) throw new WalletNotConnectedError('User email not available');
|
|
309
|
+
|
|
310
|
+
const sdk = new MetaKeep({
|
|
311
|
+
appId: this._metakeepAppId,
|
|
312
|
+
user: { email: this._email },
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
const { signatures }: { status: 'SUCCESS'; signatures: { signature: string }[] } =
|
|
316
|
+
await sdk.signTransactionMultiple(
|
|
317
|
+
transactions.map((t) => ({
|
|
318
|
+
transactionObject: t,
|
|
319
|
+
reason: 'Signing transaction using GameShift Wallet',
|
|
320
|
+
})),
|
|
321
|
+
'Signing multiple transactions using GameShift Wallet'
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
// Sign transactions one by one
|
|
325
|
+
const signedTransactions: T[] = [];
|
|
326
|
+
for (const transaction of transactions) {
|
|
327
|
+
transaction.addSignature(
|
|
328
|
+
this._publicKey,
|
|
329
|
+
Buffer.from(signatures[signedTransactions.length].signature.slice(2), 'hex')
|
|
330
|
+
);
|
|
331
|
+
signedTransactions.push(transaction);
|
|
332
|
+
}
|
|
333
|
+
return signedTransactions;
|
|
334
|
+
} catch (error: any) {
|
|
335
|
+
this.emit('error', error);
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async signMessage(message: Uint8Array): Promise<Uint8Array> {
|
|
341
|
+
try {
|
|
342
|
+
if (!this._publicKey) throw new WalletNotConnectedError();
|
|
343
|
+
if (!this._email) throw new WalletNotConnectedError('User email not available');
|
|
344
|
+
|
|
345
|
+
const sdk = new MetaKeep({
|
|
346
|
+
appId: this._metakeepAppId,
|
|
347
|
+
user: { email: this._email },
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const { signature }: { status: 'SUCCESS'; signature: string } = await sdk.signMessage(
|
|
351
|
+
Buffer.from(message).toString(),
|
|
352
|
+
'Signing message using GameShift Wallet'
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
return Buffer.from(signature.slice(2), 'hex');
|
|
356
|
+
} catch (error: any) {
|
|
357
|
+
this.emit('error', error);
|
|
358
|
+
throw error;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private _cleanup(): void {
|
|
363
|
+
if (this._messageHandler) {
|
|
364
|
+
window.removeEventListener('message', this._messageHandler);
|
|
365
|
+
this._messageHandler = null;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (this._popupCheckInterval) {
|
|
369
|
+
clearInterval(this._popupCheckInterval);
|
|
370
|
+
this._popupCheckInterval = null;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (this._popup) {
|
|
374
|
+
try {
|
|
375
|
+
if (!this._popup.closed) {
|
|
376
|
+
this._popup.close();
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
379
|
+
// Ignore errors when accessing cross-origin popup
|
|
380
|
+
}
|
|
381
|
+
this._popup = null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './adapter.js';
|