@cartridge/controller
Advanced tools
Comparing version 0.1.47 to 0.1.48
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -26,29 +11,2 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -58,21 +16,18 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var cuid_1 = __importDefault(require("cuid")); | ||
var starknet_1 = require("starknet"); | ||
var number_1 = require("starknet/utils/number"); | ||
var query_string_1 = __importDefault(require("query-string")); | ||
var signer_1 = require("./signer"); | ||
var CartridgeAccount = /** @class */ (function (_super) { | ||
__extends(CartridgeAccount, _super); | ||
function CartridgeAccount(address, scopes, messenger, options) { | ||
if (scopes === void 0) { scopes = []; } | ||
var _this = _super.call(this, starknet_1.defaultProvider, address, new signer_1.Signer(messenger, options)) || this; | ||
_this.url = "https://x.cartridge.gg"; | ||
_this._scopes = []; | ||
_this.address = address; | ||
_this.messenger = messenger; | ||
_this._scopes = scopes; | ||
const cuid_1 = __importDefault(require("cuid")); | ||
const starknet_1 = require("starknet"); | ||
const number_1 = require("starknet/utils/number"); | ||
const query_string_1 = __importDefault(require("query-string")); | ||
const signer_1 = require("./signer"); | ||
class CartridgeAccount extends starknet_1.Account { | ||
constructor(address, scopes = [], messenger, options) { | ||
super(starknet_1.defaultProvider, address, new signer_1.Signer(messenger, options)); | ||
this.url = "https://x.cartridge.gg"; | ||
this._scopes = []; | ||
this.address = address; | ||
this.messenger = messenger; | ||
this._scopes = scopes; | ||
if (options === null || options === void 0 ? void 0 : options.url) { | ||
_this.url = options.url; | ||
this.url = options.url; | ||
} | ||
return _this; | ||
} | ||
@@ -89,28 +44,20 @@ /** | ||
*/ | ||
CartridgeAccount.prototype.deployContract = function (payload, abi) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var id, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
id = (0, cuid_1.default)(); | ||
window.open("".concat(this.url, "/deploy?origin=").concat(encodeURIComponent(window.origin), "&id=").concat(id), "_blank", "height=650,width=400"); | ||
return [4 /*yield*/, this.messenger.send({ | ||
method: "deploy-contract", | ||
params: { | ||
id: id, | ||
payload: payload, | ||
abi: abi, | ||
}, | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return [2 /*return*/, response.result]; | ||
} | ||
deployContract(payload, abi) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const id = (0, cuid_1.default)(); | ||
window.open(`${this.url}/deploy?origin=${encodeURIComponent(window.origin)}&id=${id}`, "_blank", "height=650,width=400"); | ||
const response = yield this.messenger.send({ | ||
method: "deploy-contract", | ||
params: { | ||
id, | ||
payload, | ||
abi, | ||
}, | ||
}); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return response.result; | ||
}); | ||
}; | ||
} | ||
/** | ||
@@ -127,37 +74,19 @@ * Estimate Fee for a method on starknet | ||
*/ | ||
CartridgeAccount.prototype.estimateFee = function (calls, _a) { | ||
var _b = _a === void 0 ? {} : _a, providedNonce = _b.nonce, blockIdentifier = _b.blockIdentifier; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var nonce, _c, _d, response; | ||
return __generator(this, function (_e) { | ||
switch (_e.label) { | ||
case 0: | ||
_c = number_1.toBN; | ||
if (!(providedNonce !== null && providedNonce !== void 0)) return [3 /*break*/, 1]; | ||
_d = providedNonce; | ||
return [3 /*break*/, 3]; | ||
case 1: return [4 /*yield*/, this.getNonce()]; | ||
case 2: | ||
_d = (_e.sent()); | ||
_e.label = 3; | ||
case 3: | ||
nonce = _c.apply(void 0, [_d]); | ||
return [4 /*yield*/, this.messenger.send({ | ||
method: "estimate-fee", | ||
params: { | ||
calls: calls, | ||
nonce: nonce, | ||
blockIdentifier: blockIdentifier, | ||
}, | ||
})]; | ||
case 4: | ||
response = _e.sent(); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return [2 /*return*/, response.result]; | ||
} | ||
estimateFee(calls, { nonce: providedNonce, blockIdentifier } = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const nonce = (0, number_1.toBN)(providedNonce !== null && providedNonce !== void 0 ? providedNonce : (yield this.getNonce())); | ||
const response = yield this.messenger.send({ | ||
method: "estimate-fee", | ||
params: { | ||
calls, | ||
nonce, | ||
blockIdentifier, | ||
}, | ||
}); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return response.result; | ||
}); | ||
}; | ||
} | ||
/** | ||
@@ -175,48 +104,39 @@ * Invoke execute function in account contract | ||
*/ | ||
CartridgeAccount.prototype.execute = function (calls, abis, transactionsDetail) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var response, id; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.messenger.send({ | ||
method: "execute", | ||
params: { | ||
calls: calls, | ||
abis: abis, | ||
transactionsDetail: transactionsDetail, | ||
}, | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
if (response.result) { | ||
return [2 /*return*/, response.result]; | ||
} | ||
if (response.error && response.error !== "missing scopes") { | ||
throw new Error(response.error); | ||
} | ||
id = (0, cuid_1.default)(); | ||
window.open("".concat(this.url, "/execute?").concat(query_string_1.default.stringify({ | ||
id: id, | ||
origin: window.origin, | ||
calls: JSON.stringify(calls), | ||
})), "_blank", "height=650,width=400"); | ||
return [4 /*yield*/, this.messenger.send({ | ||
method: "execute", | ||
params: { | ||
id: id, | ||
calls: calls, | ||
abis: abis, | ||
transactionsDetail: transactionsDetail, | ||
}, | ||
})]; | ||
case 2: | ||
response = _a.sent(); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return [2 /*return*/, response.result]; | ||
} | ||
execute(calls, abis, transactionsDetail) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let response = yield this.messenger.send({ | ||
method: "execute", | ||
params: { | ||
calls, | ||
abis, | ||
transactionsDetail, | ||
}, | ||
}); | ||
if (response.result) { | ||
return response.result; | ||
} | ||
if (response.error && response.error !== "missing scopes") { | ||
throw new Error(response.error); | ||
} | ||
const id = (0, cuid_1.default)(); | ||
window.open(`${this.url}/execute?${query_string_1.default.stringify({ | ||
id, | ||
origin: window.origin, | ||
calls: JSON.stringify(calls), | ||
})}`, "_blank", "height=650,width=400"); | ||
response = yield this.messenger.send({ | ||
method: "execute", | ||
params: { | ||
id, | ||
calls, | ||
abis, | ||
transactionsDetail, | ||
}, | ||
}); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return response.result; | ||
}); | ||
}; | ||
} | ||
/** | ||
@@ -230,34 +150,25 @@ * Sign an JSON object for off-chain usage with the starknet private key and return the signature | ||
*/ | ||
CartridgeAccount.prototype.signMessage = function (typedData) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var id, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
id = (0, cuid_1.default)(); | ||
window.open("".concat(this.url, "/sign?").concat(query_string_1.default.stringify({ | ||
id: id, | ||
origin: window.origin, | ||
typedData: JSON.stringify(typedData), | ||
})), "_blank", "height=650,width=400"); | ||
return [4 /*yield*/, this.messenger.send({ | ||
method: "sign-message", | ||
params: { | ||
id: id, | ||
typedData: typedData, | ||
}, | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return [2 /*return*/, response.result]; | ||
} | ||
signMessage(typedData) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const id = (0, cuid_1.default)(); | ||
window.open(`${this.url}/sign?${query_string_1.default.stringify({ | ||
id, | ||
origin: window.origin, | ||
typedData: JSON.stringify(typedData), | ||
})}`, "_blank", "height=650,width=400"); | ||
const response = yield this.messenger.send({ | ||
method: "sign-message", | ||
params: { | ||
id, | ||
typedData, | ||
}, | ||
}); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return response.result; | ||
}); | ||
}; | ||
return CartridgeAccount; | ||
}(starknet_1.Account)); | ||
} | ||
} | ||
exports.default = CartridgeAccount; | ||
//# sourceMappingURL=account.js.map |
224
lib/index.js
@@ -25,29 +25,2 @@ "use strict"; | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -58,10 +31,9 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.Messenger = void 0; | ||
var cuid_1 = __importDefault(require("cuid")); | ||
var query_string_1 = __importDefault(require("query-string")); | ||
var account_1 = __importDefault(require("./account")); | ||
var messenger_1 = __importDefault(require("./messenger")); | ||
const cuid_1 = __importDefault(require("cuid")); | ||
const query_string_1 = __importDefault(require("query-string")); | ||
const account_1 = __importDefault(require("./account")); | ||
const messenger_1 = __importDefault(require("./messenger")); | ||
exports.Messenger = messenger_1.default; | ||
var Controller = /** @class */ (function () { | ||
function Controller(scopes, options) { | ||
var _this = this; | ||
class Controller { | ||
constructor(scopes, options) { | ||
this.selector = "cartridge-messenger"; | ||
@@ -78,23 +50,15 @@ this.scopes = []; | ||
if (typeof document !== "undefined") { | ||
this.ready_ = new Promise(function (resolve, reject) { | ||
window.addEventListener("message", function (e) { return __awaiter(_this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!(e.data.target === "cartridge" && | ||
e.data.payload.method === "ready")) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, this.probe()]; | ||
case 1: | ||
_a.sent(); | ||
this.loading = false; | ||
resolve(true); | ||
_a.label = 2; | ||
case 2: return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
this.ready_ = new Promise((resolve, reject) => { | ||
window.addEventListener("message", (e) => __awaiter(this, void 0, void 0, function* () { | ||
if (e.data.target === "cartridge" && | ||
e.data.payload.method === "ready") { | ||
yield this.probe(); | ||
this.loading = false; | ||
resolve(true); | ||
} | ||
})); | ||
}); | ||
} | ||
if (typeof document !== "undefined" && !this.messenger) { | ||
var iframe = document.getElementById(this.selector); | ||
let iframe = document.getElementById(this.selector); | ||
if (!!iframe) { | ||
@@ -108,3 +72,3 @@ if (!this.messenger) { | ||
iframe.id = this.selector; | ||
iframe.src = "".concat(this.url); | ||
iframe.src = `${this.url}`; | ||
iframe.style.opacity = "0"; | ||
@@ -123,107 +87,77 @@ iframe.style.height = "0"; | ||
} | ||
Controller.prototype.ready = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
if (!this.loading) | ||
return [2 /*return*/, Promise.resolve(true)]; | ||
return [2 /*return*/, this.ready_]; | ||
}); | ||
ready() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.loading) | ||
return Promise.resolve(true); | ||
return this.ready_; | ||
}); | ||
}; | ||
Controller.prototype.probe = function () { | ||
} | ||
probe() { | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var probe; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: return [4 /*yield*/, ((_a = this.messenger) === null || _a === void 0 ? void 0 : _a.send({ | ||
method: "probe", | ||
}))]; | ||
case 1: | ||
probe = _c.sent(); | ||
if (this.messenger && ((_b = probe === null || probe === void 0 ? void 0 : probe.result) === null || _b === void 0 ? void 0 : _b.address)) { | ||
this.account = new account_1.default(probe.result.address, probe.result.scopes, this.messenger, { | ||
url: this.url, | ||
}); | ||
return [2 /*return*/, this.account]; | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const probe = yield ((_a = this.messenger) === null || _a === void 0 ? void 0 : _a.send({ | ||
method: "probe", | ||
})); | ||
if (this.messenger && ((_b = probe === null || probe === void 0 ? void 0 : probe.result) === null || _b === void 0 ? void 0 : _b.address)) { | ||
this.account = new account_1.default(probe.result.address, probe.result.scopes, this.messenger, { | ||
url: this.url, | ||
}); | ||
return this.account; | ||
} | ||
}); | ||
}; | ||
} | ||
// Register a new device key. | ||
Controller.prototype.register = function (address) { | ||
register(address) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var register; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, ((_a = this.messenger) === null || _a === void 0 ? void 0 : _a.send({ | ||
method: "register", | ||
params: { | ||
address: address | ||
} | ||
}))]; | ||
case 1: | ||
register = _b.sent(); | ||
if (!register || register.error) { | ||
throw new Error("registration error"); | ||
} | ||
return [2 /*return*/, register.result]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const register = yield ((_a = this.messenger) === null || _a === void 0 ? void 0 : _a.send({ | ||
method: "register", | ||
params: { | ||
address | ||
} | ||
}); | ||
})); | ||
if (!register || register.error) { | ||
throw new Error("registration error"); | ||
} | ||
return register.result; | ||
}); | ||
}; | ||
Controller.prototype.connect = function () { | ||
} | ||
connect() { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var id, ok, response; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
id = (0, cuid_1.default)(); | ||
if (this.account) { | ||
return [2 /*return*/, this.account]; | ||
} | ||
if (!!!document.hasStorageAccess) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, document.hasStorageAccess()]; | ||
case 1: | ||
ok = _b.sent(); | ||
if (!!ok) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, document.requestStorageAccess()]; | ||
case 2: | ||
_b.sent(); | ||
_b.label = 3; | ||
case 3: | ||
window.open("".concat(this.url, "/connect?").concat(query_string_1.default.stringify({ | ||
id: id, | ||
origin: window.origin, | ||
scopes: JSON.stringify(this.scopes), | ||
})), "_blank", "height=650,width=400"); | ||
return [4 /*yield*/, ((_a = this.messenger) === null || _a === void 0 ? void 0 : _a.send({ | ||
method: "connect", | ||
params: { | ||
id: id, | ||
scopes: this.scopes, | ||
}, | ||
}))]; | ||
case 4: | ||
response = _b.sent(); | ||
if (!this.messenger || !response || response.error || !response.result) { | ||
console.error("not ready for connect"); | ||
return [2 /*return*/, null]; | ||
} | ||
this.account = new account_1.default(response.result.address, response.result.scopes, this.messenger, { | ||
url: this.url, | ||
}); | ||
return [2 /*return*/, this.account]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const id = (0, cuid_1.default)(); | ||
if (this.account) { | ||
return this.account; | ||
} | ||
if (!!document.hasStorageAccess) { | ||
const ok = yield document.hasStorageAccess(); | ||
if (!ok) { | ||
yield document.requestStorageAccess(); | ||
} | ||
} | ||
window.open(`${this.url}/connect?${query_string_1.default.stringify({ | ||
id, | ||
origin: window.origin, | ||
scopes: JSON.stringify(this.scopes), | ||
})}`, "_blank", "height=650,width=400"); | ||
const response = yield ((_a = this.messenger) === null || _a === void 0 ? void 0 : _a.send({ | ||
method: "connect", | ||
params: { | ||
id, | ||
scopes: this.scopes, | ||
}, | ||
})); | ||
if (!this.messenger || !response || response.error || !response.result) { | ||
console.error("not ready for connect"); | ||
return null; | ||
} | ||
this.account = new account_1.default(response.result.address, response.result.scopes, this.messenger, { | ||
url: this.url, | ||
}); | ||
return this.account; | ||
}); | ||
}; | ||
return Controller; | ||
}()); | ||
} | ||
} | ||
exports.default = Controller; | ||
__exportStar(require("./types"), exports); | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -17,12 +6,10 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var cuid_1 = __importDefault(require("cuid")); | ||
var Messenger = /** @class */ (function () { | ||
function Messenger(target, origin) { | ||
if (origin === void 0) { origin = "https://x.cartridge.gg"; } | ||
var _this = this; | ||
const cuid_1 = __importDefault(require("cuid")); | ||
class Messenger { | ||
constructor(target, origin = "https://x.cartridge.gg") { | ||
this.pending = []; | ||
this.defaultHandler = function (e) { | ||
this.defaultHandler = (e) => { | ||
if (e.data.target === "cartridge" && | ||
e.data.type === "request") { | ||
_this.pending.push(e); | ||
this.pending.push(e); | ||
} | ||
@@ -38,24 +25,21 @@ }; | ||
} | ||
Messenger.prototype.onRequest = function (cb) { | ||
onRequest(cb) { | ||
window.removeEventListener("message", this.defaultHandler); | ||
var onResponse = function (_a) { | ||
var origin = _a.origin, source = _a.source, id = _a.data.id; | ||
return function (response) { | ||
if (!source) { | ||
return; | ||
} | ||
source.postMessage({ | ||
id: id, | ||
target: "cartridge", | ||
type: "response", | ||
payload: __assign({ origin: window.origin }, response), | ||
}, { targetOrigin: origin }); | ||
}; | ||
const onResponse = ({ origin, source, data: { id }, }) => (response) => { | ||
if (!source) { | ||
return; | ||
} | ||
source.postMessage({ | ||
id, | ||
target: "cartridge", | ||
type: "response", | ||
payload: Object.assign({ origin: window.origin }, response), | ||
}, { targetOrigin: origin }); | ||
}; | ||
for (var i = 0; i < this.pending.length; i++) { | ||
var payload = this.pending[i].data.payload; | ||
for (let i = 0; i < this.pending.length; i++) { | ||
const { data: { payload }, } = this.pending[i]; | ||
cb(payload, onResponse(this.pending[i])); | ||
} | ||
window.addEventListener("message", function (e) { | ||
var _a = e.data, type = _a.type, target = _a.target, payload = _a.payload; | ||
window.addEventListener("message", (e) => { | ||
const { data: { type, target, payload }, } = e; | ||
if (target === "cartridge" && | ||
@@ -66,5 +50,5 @@ type === "request") { | ||
}); | ||
}; | ||
Messenger.prototype.send = function (request) { | ||
var id = (0, cuid_1.default)(); | ||
} | ||
send(request) { | ||
const id = (0, cuid_1.default)(); | ||
if (!this.target) { | ||
@@ -74,10 +58,9 @@ throw new Error("read only"); | ||
this.target.postMessage({ | ||
id: id, | ||
id, | ||
target: "cartridge", | ||
type: "request", | ||
payload: __assign({ origin: window.origin }, request), | ||
payload: Object.assign({ origin: window.origin }, request), | ||
}, this.origin); | ||
return new Promise(function (resolve, reject) { | ||
var handler = function (_a) { | ||
var data = _a.data; | ||
return new Promise((resolve, reject) => { | ||
const handler = ({ data }) => { | ||
if (data.target === "cartridge" && | ||
@@ -92,6 +75,5 @@ data.type === "response" && | ||
}); | ||
}; | ||
return Messenger; | ||
}()); | ||
} | ||
} | ||
exports.default = Messenger; | ||
//# sourceMappingURL=messenger.js.map |
@@ -11,29 +11,2 @@ "use strict"; | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -44,6 +17,6 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.Signer = void 0; | ||
var query_string_1 = __importDefault(require("query-string")); | ||
var cuid_1 = __importDefault(require("cuid")); | ||
var Signer = /** @class */ (function () { | ||
function Signer(messenger, options) { | ||
const query_string_1 = __importDefault(require("query-string")); | ||
const cuid_1 = __importDefault(require("cuid")); | ||
class Signer { | ||
constructor(messenger, options) { | ||
this.url = "https://cartridge.gg"; | ||
@@ -60,5 +33,5 @@ this.messenger = messenger; | ||
*/ | ||
Signer.prototype.getPubKey = function () { | ||
getPubKey() { | ||
return Promise.resolve(""); | ||
}; | ||
} | ||
/** | ||
@@ -73,32 +46,24 @@ * Sign an JSON object for off-chain usage with the starknet private key and return the signature | ||
*/ | ||
Signer.prototype.signMessage = function (typedData, account) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var id, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
id = (0, cuid_1.default)(); | ||
window.open("".concat(this.url, "/sign?").concat(query_string_1.default.stringify({ | ||
id: id, | ||
origin: window.origin, | ||
message: JSON.stringify(typedData.message), | ||
})), "_blank", "height=650,width=400"); | ||
return [4 /*yield*/, this.messenger.send({ | ||
method: "sign-message", | ||
params: { | ||
id: id, | ||
account: account, | ||
typedData: typedData, | ||
}, | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return [2 /*return*/, response.result]; | ||
} | ||
signMessage(typedData, account) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const id = (0, cuid_1.default)(); | ||
window.open(`${this.url}/sign?${query_string_1.default.stringify({ | ||
id, | ||
origin: window.origin, | ||
message: JSON.stringify(typedData.message), | ||
})}`, "_blank", "height=650,width=400"); | ||
const response = yield this.messenger.send({ | ||
method: "sign-message", | ||
params: { | ||
id, | ||
account, | ||
typedData, | ||
}, | ||
}); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return response.result; | ||
}); | ||
}; | ||
} | ||
/** | ||
@@ -116,37 +81,28 @@ * Signs a transaction with the starknet private key and returns the signature | ||
*/ | ||
Signer.prototype.signTransaction = function (transactions, transactionsDetail, abis) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var id, calls, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
id = (0, cuid_1.default)(); | ||
calls = Array.isArray(transactions) ? transactions : [transactions]; | ||
window.open("".concat(this.url, "/sign?").concat(query_string_1.default.stringify({ | ||
id: id, | ||
origin: window.origin, | ||
calls: JSON.stringify(calls), | ||
})), "_blank", "height=650,width=400"); | ||
return [4 /*yield*/, this.messenger.send({ | ||
method: "sign-transaction", | ||
params: { | ||
id: id, | ||
transactions: transactions, | ||
abis: abis, | ||
transactionsDetail: transactionsDetail, | ||
}, | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return [2 /*return*/, response.result]; | ||
} | ||
signTransaction(transactions, transactionsDetail, abis) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const id = (0, cuid_1.default)(); | ||
const calls = Array.isArray(transactions) ? transactions : [transactions]; | ||
window.open(`${this.url}/sign?${query_string_1.default.stringify({ | ||
id, | ||
origin: window.origin, | ||
calls: JSON.stringify(calls), | ||
})}`, "_blank", "height=650,width=400"); | ||
const response = yield this.messenger.send({ | ||
method: "sign-transaction", | ||
params: { | ||
id, | ||
transactions, | ||
abis, | ||
transactionsDetail, | ||
}, | ||
}); | ||
if (response.error) { | ||
throw new Error(response.error); | ||
} | ||
return response.result; | ||
}); | ||
}; | ||
return Signer; | ||
}()); | ||
} | ||
} | ||
exports.Signer = Signer; | ||
//# sourceMappingURL=signer.js.map |
"use strict"; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -16,9 +7,7 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.diff = void 0; | ||
var fast_deep_equal_1 = __importDefault(require("fast-deep-equal")); | ||
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal")); | ||
function diff(a, b) { | ||
return a.reduce(function (prev, scope) { | ||
return b.some(function (approval) { return (0, fast_deep_equal_1.default)(approval, scope); }) ? prev : __spreadArray(__spreadArray([], prev, true), [scope], false); | ||
}, []); | ||
return a.reduce((prev, scope) => b.some((approval) => (0, fast_deep_equal_1.default)(approval, scope)) ? prev : [...prev, scope], []); | ||
} | ||
exports.diff = diff; | ||
//# sourceMappingURL=utils.js.map |
@@ -11,38 +11,2 @@ "use strict"; | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -53,10 +17,10 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.WebauthnSigner = void 0; | ||
var starknet_1 = require("starknet"); | ||
var base64url_1 = __importDefault(require("base64url")); | ||
var BASE = starknet_1.number.toBN(2).pow(86); | ||
const starknet_1 = require("starknet"); | ||
const base64url_1 = __importDefault(require("base64url")); | ||
const BASE = starknet_1.number.toBN(2).pow(86); | ||
function split(n) { | ||
var x = n.mod(BASE); | ||
var y = n.div(BASE).mod(BASE); | ||
var z = n.div(BASE).div(BASE); | ||
return { x: x, y: y, z: z }; | ||
const x = n.mod(BASE); | ||
const y = n.div(BASE).mod(BASE); | ||
const z = n.div(BASE).div(BASE); | ||
return { x, y, z }; | ||
} | ||
@@ -77,63 +41,54 @@ function convertUint8ArrayToWordArray(u8Array) { | ||
} | ||
var WebauthnSigner = /** @class */ (function () { | ||
function WebauthnSigner(credentialId, publicKey) { | ||
class WebauthnSigner { | ||
constructor(credentialId, publicKey) { | ||
this.credentialId = credentialId; | ||
this.publicKey = publicKey; | ||
} | ||
WebauthnSigner.prototype.getPubKey = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.publicKey]; | ||
}); | ||
getPubKey() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this.publicKey; | ||
}); | ||
}; | ||
WebauthnSigner.prototype.sign = function (hash) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var challenge; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
challenge = Buffer.from(hash.slice(2).padStart(64, "0").slice(0, 64), "hex"); | ||
return [4 /*yield*/, navigator.credentials.get({ | ||
publicKey: { | ||
challenge: challenge, | ||
timeout: 60000, | ||
rpId: "cartridge.gg", | ||
allowCredentials: [ | ||
{ | ||
type: "public-key", | ||
id: base64url_1.default.toBuffer(this.credentialId), | ||
}, | ||
], | ||
userVerification: "required", | ||
}, | ||
})]; | ||
case 1: return [2 /*return*/, (_a.sent())]; | ||
} | ||
}); | ||
} | ||
sign(hash) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const challenge = Buffer.from(hash.slice(2).padStart(64, "0").slice(0, 64), "hex"); | ||
return (yield navigator.credentials.get({ | ||
publicKey: { | ||
challenge, | ||
timeout: 60000, | ||
rpId: "cartridge.gg", | ||
allowCredentials: [ | ||
{ | ||
type: "public-key", | ||
id: base64url_1.default.toBuffer(this.credentialId), | ||
}, | ||
], | ||
userVerification: "required", | ||
}, | ||
})); | ||
}); | ||
}; | ||
WebauthnSigner.prototype.formatAssertion = function (assertion) { | ||
} | ||
formatAssertion(assertion) { | ||
var authenticatorDataBytes = new Uint8Array(assertion.response.authenticatorData); | ||
var authenticatorDataRem = 4 - (authenticatorDataBytes.length % 4); | ||
let authenticatorDataRem = 4 - (authenticatorDataBytes.length % 4); | ||
if (authenticatorDataRem == 4) { | ||
authenticatorDataRem = 0; | ||
} | ||
var authenticatorDataWords = convertUint8ArrayToWordArray(authenticatorDataBytes).words; | ||
const authenticatorDataWords = convertUint8ArrayToWordArray(authenticatorDataBytes).words; | ||
var clientDataJSONBytes = new Uint8Array(assertion.response.clientDataJSON); | ||
var clientDataJSONRem = 4 - (clientDataJSONBytes.length % 4); | ||
let clientDataJSONRem = 4 - (clientDataJSONBytes.length % 4); | ||
if (clientDataJSONRem == 4) { | ||
clientDataJSONRem = 0; | ||
} | ||
var clientDataWords = convertUint8ArrayToWordArray(clientDataJSONBytes).words; | ||
const clientDataWords = convertUint8ArrayToWordArray(clientDataJSONBytes).words; | ||
// Convert signature from ASN.1 sequence to "raw" format | ||
var usignature = new Uint8Array(assertion.response.signature); | ||
var rStart = usignature[4] === 0 ? 5 : 4; | ||
var rEnd = rStart + 32; | ||
var sStart = usignature[rEnd + 2] === 0 ? rEnd + 3 : rEnd + 2; | ||
var r = starknet_1.number.toBN("0x" + Buffer.from(usignature.slice(rStart, rEnd)).toString("hex")); | ||
var s = starknet_1.number.toBN("0x" + Buffer.from(usignature.slice(sStart)).toString("hex")); | ||
var _a = split(r), r0 = _a.x, r1 = _a.y, r2 = _a.z; | ||
var _b = split(s), s0 = _b.x, s1 = _b.y, s2 = _b.z; | ||
return __spreadArray(__spreadArray(__spreadArray([ | ||
const usignature = new Uint8Array(assertion.response.signature); | ||
const rStart = usignature[4] === 0 ? 5 : 4; | ||
const rEnd = rStart + 32; | ||
const sStart = usignature[rEnd + 2] === 0 ? rEnd + 3 : rEnd + 2; | ||
const r = starknet_1.number.toBN("0x" + Buffer.from(usignature.slice(rStart, rEnd)).toString("hex")); | ||
const s = starknet_1.number.toBN("0x" + Buffer.from(usignature.slice(sStart)).toString("hex")); | ||
const { x: r0, y: r1, z: r2 } = split(r); | ||
const { x: s0, y: s1, z: s2 } = split(s); | ||
return [ | ||
"0", | ||
@@ -148,10 +103,11 @@ r0.toString(), | ||
"0", | ||
"".concat(clientDataWords.length), | ||
"".concat(clientDataJSONRem) | ||
], clientDataWords.map(function (word) { return "".concat(word); }), true), [ | ||
"".concat(authenticatorDataWords.length), | ||
"".concat(authenticatorDataRem) | ||
], false), authenticatorDataWords.map(function (word) { return "".concat(word); }), true); | ||
}; | ||
WebauthnSigner.prototype.hashTransaction = function (transactions, transactionsDetail, abis) { | ||
`${clientDataWords.length}`, | ||
`${clientDataJSONRem}`, | ||
...clientDataWords.map((word) => `${word}`), | ||
`${authenticatorDataWords.length}`, | ||
`${authenticatorDataRem}`, | ||
...authenticatorDataWords.map((word) => `${word}`), | ||
]; | ||
} | ||
hashTransaction(transactions, transactionsDetail, abis) { | ||
if (abis && abis.length !== transactions.length) { | ||
@@ -161,42 +117,26 @@ throw new Error("ABI must be provided for each transaction or no transaction"); | ||
// now use abi to display decoded data somewhere, but as this signer is headless, we can't do that | ||
var calldata = starknet_1.transaction.fromCallsToExecuteCalldataWithNonce(transactions, transactionsDetail.nonce); | ||
const calldata = starknet_1.transaction.fromCallsToExecuteCalldataWithNonce(transactions, transactionsDetail.nonce); | ||
return starknet_1.hash.calculateTransactionHash(transactionsDetail.walletAddress, transactionsDetail.version, [starknet_1.hash.getSelectorFromName("__execute__")].concat(calldata), transactionsDetail.maxFee, transactionsDetail.chainId, transactionsDetail.nonce); | ||
}; | ||
WebauthnSigner.prototype.signTransaction = function (calls, transactionsDetail, abis) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var calldata, msgHash, assertion; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (abis && abis.length !== calls.length) { | ||
throw new Error("ABI must be provided for each transaction or no transaction"); | ||
} | ||
calldata = starknet_1.transaction.fromCallsToExecuteCalldataWithNonce(calls, transactionsDetail.nonce); | ||
msgHash = starknet_1.hash.calculateTransactionHash(transactionsDetail.walletAddress, transactionsDetail.version, [starknet_1.hash.getSelectorFromName("__execute__")].concat(calldata), transactionsDetail.maxFee, transactionsDetail.chainId, transactionsDetail.nonce); | ||
return [4 /*yield*/, this.sign(msgHash)]; | ||
case 1: | ||
assertion = _a.sent(); | ||
return [2 /*return*/, this.formatAssertion(assertion)]; | ||
} | ||
}); | ||
} | ||
signTransaction(calls, transactionsDetail, abis) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (abis && abis.length !== calls.length) { | ||
throw new Error("ABI must be provided for each transaction or no transaction"); | ||
} | ||
// now use abi to display decoded data somewhere, but as this signer is headless, we can't do that | ||
const calldata = starknet_1.transaction.fromCallsToExecuteCalldataWithNonce(calls, transactionsDetail.nonce); | ||
const msgHash = starknet_1.hash.calculateTransactionHash(transactionsDetail.walletAddress, transactionsDetail.version, [starknet_1.hash.getSelectorFromName("__execute__")].concat(calldata), transactionsDetail.maxFee, transactionsDetail.chainId, transactionsDetail.nonce); | ||
const assertion = yield this.sign(msgHash); | ||
return this.formatAssertion(assertion); | ||
}); | ||
}; | ||
WebauthnSigner.prototype.signMessage = function (td, accountAddress) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var msgHash, assertion; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
msgHash = starknet_1.typedData.getMessageHash(td, accountAddress); | ||
return [4 /*yield*/, this.sign(msgHash)]; | ||
case 1: | ||
assertion = _a.sent(); | ||
return [2 /*return*/, this.formatAssertion(assertion)]; | ||
} | ||
}); | ||
} | ||
signMessage(td, accountAddress) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const msgHash = starknet_1.typedData.getMessageHash(td, accountAddress); | ||
const assertion = yield this.sign(msgHash); | ||
return this.formatAssertion(assertion); | ||
}); | ||
}; | ||
return WebauthnSigner; | ||
}()); | ||
} | ||
} | ||
exports.WebauthnSigner = WebauthnSigner; | ||
//# sourceMappingURL=webauthn.js.map |
{ | ||
"name": "@cartridge/controller", | ||
"version": "0.1.47", | ||
"version": "0.1.48", | ||
"description": "Cartridge Controller", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
54749
931