@mai3/phaser-sdk
Version:
A UI component library based on the Phaser game engine
390 lines (389 loc) • 17.7 kB
JavaScript
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
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 = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["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 (g && (g = 0, op[0] && (_ = 0)), _) 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 };
}
};
import { getHttpV4Endpoint, TonConnectUI, Address, AssetsSDK, TonClient4, beginCell } from './external';
import { TonConnectSender } from './ton-connect-sender';
import { ProxyContentResolver } from './content-resolver';
/**
* GameFiBase is a parent for every implementation of GameFi.
* Game engine specific implementations like Phaser only needs to define
* its own `create` and `createConnectButton` methods.
*/
var GameFiBase = /** @class */ (function () {
function GameFiBase(params) {
if (params.assetsSdk.sender == null) {
throw new Error('Sender is not configured.');
}
this.walletConnector = params.walletConnector;
this.assetsSdk = params.assetsSdk;
this.sender = params.assetsSdk.sender;
if (params.merchant != null) {
this.merchant = params.merchant;
}
}
Object.defineProperty(GameFiBase.prototype, "wallet", {
get: function () {
if (this.walletConnector.wallet == null) {
throw new Error('Connect a wallet before using it.');
}
return this.walletConnector.wallet;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GameFiBase.prototype, "walletAccount", {
get: function () {
return this.wallet.account;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GameFiBase.prototype, "walletAddress", {
get: function () {
return Address.parseRaw(this.wallet.account.address);
},
enumerable: false,
configurable: true
});
Object.defineProperty(GameFiBase.prototype, "merchantAddress", {
get: function () {
if (this.merchant == null || this.merchant.tonAddress == null) {
throw new Error('To make payments with TON pass "merchant.tonAddress" parameter to "GameFi.create" method.');
}
return this.merchant.tonAddress;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GameFiBase.prototype, "merchantJettonAddress", {
get: function () {
if (this.merchant == null || this.merchant.jettonAddress == null) {
throw new Error('To make payments with jetton pass "merchant.jettonAddress" parameter to "GameFi.create" method.');
}
return this.merchant.jettonAddress;
},
enumerable: false,
configurable: true
});
/**
* Send TON to merchant wallet address (in-game shop).
*/
GameFiBase.prototype.buyWithTon = function (params) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.transferTon(__assign(__assign({}, params), { to: this.merchantAddress }));
return [2 /*return*/];
});
});
};
/**
* Send TON to other wallet address.
*/
GameFiBase.prototype.transferTon = function (params) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (this.assetsSdk.sender == null) {
throw new Error('Sender is not configured.');
}
return [2 /*return*/, this.assetsSdk.sender.send({
to: params.to,
value: params.amount,
body: params.comment ? this.createMessagePayload(params.comment) : null
})];
});
});
};
/**
* Send jetton to merchant wallet address (in-game shop).
*/
GameFiBase.prototype.buyWithJetton = function (params) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.transferJetton(__assign(__assign({}, params), { to: this.merchantAddress }));
return [2 /*return*/];
});
});
};
/**
* Send jetton to other wallet address.
*/
GameFiBase.prototype.transferJetton = function (params) {
return __awaiter(this, void 0, void 0, function () {
var jetton, jettonWallet, options;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
jetton = this.assetsSdk.openJetton(this.merchantJettonAddress);
return [4 /*yield*/, jetton.getWallet(this.walletAddress)];
case 1:
jettonWallet = _a.sent();
options = {
returnExcess: {
address: this.walletAddress
}
};
if (params.customPayload != null) {
options.customPayload = this.createMessagePayload(params.customPayload);
}
if (params.forwardAmount != null || params.forwardPayload != null) {
options.notify = {};
if (params.forwardAmount != null) {
options.notify.amount = params.forwardAmount;
}
if (params.forwardPayload != null) {
options.notify.payload = this.createMessagePayload(params.forwardPayload);
}
}
return [2 /*return*/, jettonWallet.send(this.sender, params.to, params.amount, options)];
}
});
});
};
/**
* Open NFT collection contract.
*/
GameFiBase.prototype.openNftCollection = function (address) {
return this.assetsSdk.openNftCollection(address);
};
/**
* Open NFT sale contract.
*/
GameFiBase.prototype.openNftSale = function (address) {
return this.assetsSdk.openNftSale(address);
};
/**
* Open NFT contract.
*/
GameFiBase.prototype.openNftItem = function (address) {
return this.assetsSdk.openNftItem(address);
};
/**
* Get NFT item from collection using its index.
*/
GameFiBase.prototype.openNftItemByIndex = function (collectionAddress, itemIndex) {
return __awaiter(this, void 0, void 0, function () {
var nftAddress;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.assetsSdk
.openNftCollection(collectionAddress)
.getItemAddress(itemIndex)];
case 1:
nftAddress = _a.sent();
return [2 /*return*/, this.assetsSdk.openNftItem(nftAddress)];
}
});
});
};
/**
* Open SBT collection contract.
*/
GameFiBase.prototype.openSbtCollection = function (address) {
return this.assetsSdk.openSbtCollection(address);
};
/**
* Open Jetton contract.
*/
GameFiBase.prototype.openJetton = function (address) {
return this.assetsSdk.openJetton(address);
};
/**
* Open Jetton Wallet contract.
*/
GameFiBase.prototype.openJettonWallet = function (address) {
return this.assetsSdk.openJettonWallet(address);
};
/**
* Call connectWallet programmatically in case
* you are not going to use TonConnectUI provided UI or game engine provided button
* and you draw your own UI.
*/
GameFiBase.prototype.connectWallet = function (app) {
return this.walletConnector.openSingleWalletModal(app);
};
/**
* Watch weather wallet was connected or disconnected.
* Use the method to reflect it on the UI state.
*/
GameFiBase.prototype.onWalletChange = function () {
var _a;
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
var unsubscribe = (_a = this.walletConnector).onStatusChange.apply(_a, params);
// by default onStatusChange doesn't trigger when no wallet to restore
// do manually trigger to user doesn't need to handle the case by himself
this.walletConnector.connectionRestored.then(function (connected) {
if (!connected) {
params[0](null);
}
});
return unsubscribe;
};
/**
* Call connectWallet programmatically in case
* you draw your own UI.
*/
GameFiBase.prototype.disconnectWallet = function () {
return this.walletConnector.disconnect();
};
GameFiBase.prototype.createMessagePayload = function (message) {
return beginCell().storeUint(0, 32).storeStringTail(message).endCell();
};
/**
* Prepares dependencies to game engine implementations use it for `create` method.
* These dependencies will be used to create an GameFi instance further.
*/
GameFiBase.createDependencies = function () {
return __awaiter(this, arguments, void 0, function (params) {
var connector, client, _a, network, merchant, walletConnector, tonClient, clientParams, endpoint, contentResolverParams, _b, ipfsGateway, urlProxy_1, contentResolver, assetsSdk, dependencies;
if (params === void 0) { params = {}; }
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
connector = params.connector, client = params.client, _a = params.network, network = _a === void 0 ? 'testnet' : _a, merchant = params.merchant;
walletConnector = GameFiBase.isTonConnectUiInstance(connector)
? connector
: GameFiBase.createConnectUiWorkaround(connector);
if (!(client instanceof TonClient4)) return [3 /*break*/, 1];
tonClient = client;
return [3 /*break*/, 5];
case 1:
clientParams = void 0;
if (!(client == null)) return [3 /*break*/, 3];
return [4 /*yield*/, getHttpV4Endpoint({
network: network
})];
case 2:
endpoint = _c.sent();
clientParams = { endpoint: endpoint };
return [3 /*break*/, 4];
case 3:
clientParams = client;
_c.label = 4;
case 4:
tonClient = new TonClient4(clientParams);
_c.label = 5;
case 5:
contentResolverParams = {};
if (params.contentResolver != null) {
_b = params.contentResolver, ipfsGateway = _b.ipfsGateway, urlProxy_1 = _b.urlProxy;
if (ipfsGateway != null) {
contentResolverParams.ipfsGateway = ipfsGateway;
}
if (urlProxy_1 != null) {
if (typeof urlProxy_1 === 'string') {
contentResolverParams.urlProxy = function (url) {
return urlProxy_1.replace(ProxyContentResolver.replaceable, url);
};
}
else {
contentResolverParams.urlProxy = urlProxy_1;
}
}
}
contentResolver = new ProxyContentResolver(contentResolverParams);
assetsSdk = AssetsSDK.create({
api: tonClient,
contentResolver: contentResolver,
sender: new TonConnectSender(walletConnector)
});
dependencies = {
walletConnector: walletConnector,
assetsSdk: assetsSdk
};
if (merchant != null) {
dependencies.merchant = {
tonAddress: GameFiBase.addressToObject(merchant.tonAddress)
};
if (merchant.jettonAddress != null) {
dependencies.merchant.jettonAddress = GameFiBase.addressToObject(merchant.jettonAddress);
}
}
return [2 /*return*/, dependencies];
}
});
});
};
GameFiBase.addressToObject = function (address) {
if (typeof address === 'string') {
return Address.parse(address);
}
return address;
};
GameFiBase.isTonConnectUiInstance = function (instance) {
// because TonConnectUI cleared outside of the lib, in a consumer app
// instance instanceof TonConnectUI returns false
// so we need implement the check differently
// todo figure out how to fix
return typeof instance === 'object' && instance != null && 'openModal' in instance;
};
GameFiBase.createConnectUiWorkaround = function (params) {
if (params === void 0) { params = {}; }
// we need 100% TonConnectUI functionality, but without visual parts
// to reuse the logic, but not to implement fork, use the workaround
// todo remove this workaround
var hide = function (element) {
element.style.overflow = 'hidden';
element.style.display = 'none';
element.style.position = 'absolute';
element.style.left = '-9999px';
};
var buttonRoot = document.createElement('div');
buttonRoot.id = '__ton-connect-ui--button-root';
hide(buttonRoot);
document.body.appendChild(buttonRoot);
var widgetRoot = document.createElement('div');
widgetRoot.id = '__ton-connect-ui--widget-root';
hide(widgetRoot);
document.body.appendChild(widgetRoot);
return new TonConnectUI(__assign(__assign({}, params), { buttonRootId: buttonRoot.id, widgetRootId: widgetRoot.id }));
};
return GameFiBase;
}());
export { GameFiBase };