@tonconnect/sdk
Advanced tools
Comparing version 0.0.36 to 0.0.37
@@ -5,3 +5,4 @@ /** | ||
export declare class TonConnectError extends Error { | ||
constructor(...args: ConstructorParameters<typeof Error>); | ||
private static prefix; | ||
constructor(message?: string, options?: ErrorOptions); | ||
} |
@@ -8,4 +8,7 @@ "use strict"; | ||
class TonConnectError extends Error { | ||
constructor(...args) { | ||
super(...args); | ||
constructor(message, options) { | ||
if (message) { | ||
message = TonConnectError.prefix + ' ' + message; | ||
} | ||
super(message, options); | ||
Object.setPrototypeOf(this, TonConnectError.prototype); | ||
@@ -15,1 +18,2 @@ } | ||
exports.TonConnectError = TonConnectError; | ||
TonConnectError.prefix = '[TON_CONNECT_SDK_ERROR]'; |
@@ -1,2 +0,1 @@ | ||
import { DappMetadata } from "./dapp/dapp-metadata"; | ||
import { IStorage } from "../storage/models/storage.interface"; | ||
@@ -8,6 +7,6 @@ /** | ||
/** | ||
* Dapp metadata that will be displayed in the user's wallet. | ||
* Options will be merged with the [defaults]{@link ./dapp/dappMetedata.ts} if there are some empty fields. | ||
* Url to the [manifest]{@link https://github.com/ton-connect/docs/blob/main/requests-responses.md#app-manifest} with the Dapp metadata that will be displayed in the user's wallet. | ||
* If not passed, manifest from `${window.location.origin}/tonconnect-manifest.json` will be taken. | ||
*/ | ||
dappMetedata?: Partial<DappMetadata>; | ||
manifestUrl?: string; | ||
/** | ||
@@ -14,0 +13,0 @@ * Storage to save protocol data. For browser default is `localStorage`. If you use SDK with nodeJS, you have to specify this field. |
@@ -11,2 +11,7 @@ import { CHAIN } from '@tonconnect/protocol'; | ||
chain: CHAIN; | ||
/** | ||
* Base64 (not url safe) encoded wallet contract stateInit. | ||
* Can be used to get user's public key from the stateInit if the wallet contract doesn't support corresponding get method. | ||
*/ | ||
walletStateInit: string; | ||
} |
@@ -5,2 +5,4 @@ "use strict"; | ||
const errors_1 = require("../errors"); | ||
const manifest_content_error_error_1 = require("../errors/protocol/events/connect/manifest-content-error.error"); | ||
const manifest_not_found_error_1 = require("../errors/protocol/events/connect/manifest-not-found.error"); | ||
const unknown_error_1 = require("../errors/unknown.error"); | ||
@@ -12,3 +14,5 @@ const protocol_1 = require("@tonconnect/protocol"); | ||
[protocol_1.CONNECT_EVENT_ERROR_CODES.BAD_REQUEST_ERROR]: errors_1.BadRequestError, | ||
[protocol_1.CONNECT_EVENT_ERROR_CODES.UNKNOWN_APP_ERROR]: errors_1.UnknownAppError | ||
[protocol_1.CONNECT_EVENT_ERROR_CODES.UNKNOWN_APP_ERROR]: errors_1.UnknownAppError, | ||
[protocol_1.CONNECT_EVENT_ERROR_CODES.MANIFEST_NOT_FOUND_ERROR]: manifest_not_found_error_1.ManifestNotFoundError, | ||
[protocol_1.CONNECT_EVENT_ERROR_CODES.MANIFEST_CONTENT_ERROR]: manifest_content_error_error_1.ManifestContentErrorError | ||
}; | ||
@@ -15,0 +19,0 @@ class ConnectErrorsParser { |
@@ -25,2 +25,4 @@ "use strict"; | ||
const dapp_metadata_error_1 = require("./errors/dapp/dapp-metadata.error"); | ||
const manifest_content_error_error_1 = require("./errors/protocol/events/connect/manifest-content-error.error"); | ||
const manifest_not_found_error_1 = require("./errors/protocol/events/connect/manifest-not-found.error"); | ||
const ton_connect_error_1 = require("./errors/ton-connect.error"); | ||
@@ -36,3 +38,2 @@ const wallet_already_connected_error_1 = require("./errors/wallet/wallet-already-connected.error"); | ||
const default_storage_1 = require("./storage/default-storage"); | ||
const options_1 = require("./utils/options"); | ||
const web_api_1 = require("./utils/web-api"); | ||
@@ -48,7 +49,7 @@ const wallets_list_manager_1 = require("./wallets-list-manager"); | ||
this.dappSettings = { | ||
dappMetedata: (0, options_1.mergeOptions)(options === null || options === void 0 ? void 0 : options.dappMetedata, (0, web_api_1.getWebPageMetadata)()), | ||
manifestUrl: (options === null || options === void 0 ? void 0 : options.manifestUrl) || (0, web_api_1.getWebPageManifest)(), | ||
storage: (options === null || options === void 0 ? void 0 : options.storage) || new default_storage_1.DefaultStorage() | ||
}; | ||
if (!this.dappSettings.dappMetedata.url) { | ||
throw new dapp_metadata_error_1.DappMetadataError('Dapp url must be specified if window.location.origin is undefined.'); | ||
if (!this.dappSettings.manifestUrl) { | ||
throw new dapp_metadata_error_1.DappMetadataError('Dapp tonconnect-manifest.json must be specified if window.location.origin is undefined. See more https://github.com/ton-connect/docs/blob/main/requests-responses.md#app-manifest'); | ||
} | ||
@@ -204,3 +205,4 @@ this.bridgeConnectionStorage = new bridge_connection_storage_1.BridgeConnectionStorage(this.dappSettings.storage); | ||
address: tonAccountItem.address, | ||
chain: tonAccountItem.network | ||
chain: tonAccountItem.network, | ||
walletStateInit: tonAccountItem.walletStateInit | ||
} | ||
@@ -218,2 +220,6 @@ }; | ||
this.statusChangeErrorSubscriptions.forEach(errorsHandler => errorsHandler(error)); | ||
if (error instanceof manifest_not_found_error_1.ManifestNotFoundError || error instanceof manifest_content_error_error_1.ManifestContentErrorError) { | ||
console.error(error); | ||
throw error; | ||
} | ||
} | ||
@@ -229,4 +235,2 @@ onWalletDisconnected() { | ||
createConnectRequest(request) { | ||
const webPageMetadata = (0, web_api_1.getWebPageMetadata)(); | ||
const metadata = (0, options_1.mergeOptions)(this.dappSettings.dappMetedata, webPageMetadata); | ||
const items = [ | ||
@@ -243,5 +247,8 @@ { | ||
} | ||
return Object.assign(Object.assign({}, metadata), { items }); | ||
return { | ||
manifestUrl: this.dappSettings.manifestUrl, | ||
items | ||
}; | ||
} | ||
} | ||
exports.TonConnect = TonConnect; |
@@ -1,4 +0,3 @@ | ||
import { DappMetadata } from "../models"; | ||
export declare function getWindow(): Window | undefined; | ||
export declare function getDocument(): Document | undefined; | ||
export declare function getWebPageMetadata(): DappMetadata; | ||
export declare function getWebPageManifest(): string; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getWebPageMetadata = exports.getDocument = exports.getWindow = void 0; | ||
exports.getWebPageManifest = exports.getDocument = exports.getWindow = void 0; | ||
function getWindow() { | ||
@@ -18,60 +18,10 @@ if (typeof window === 'undefined') { | ||
exports.getDocument = getDocument; | ||
function getWebPageMetadata() { | ||
var _a, _b; | ||
return { | ||
url: ((_a = getWindow()) === null || _a === void 0 ? void 0 : _a.location.origin) || '', | ||
icon: getIconUrl(), | ||
name: ((_b = getDocument()) === null || _b === void 0 ? void 0 : _b.title) || 'Unknown dapp' | ||
}; | ||
} | ||
exports.getWebPageMetadata = getWebPageMetadata; | ||
function getIconUrl() { | ||
const document = getDocument(); | ||
if (!document) { | ||
return ''; | ||
} | ||
const appleTouchIcons = document.querySelectorAll("link[rel='apple-touch-icon']"); | ||
if (appleTouchIcons === null || appleTouchIcons === void 0 ? void 0 : appleTouchIcons.length) { | ||
return getLargestSizeIconUrl(Array.from(appleTouchIcons)); | ||
} | ||
const links = Array.from(document.querySelectorAll("link[rel*='icon']")); | ||
const pngLinks = links.filter(link => link.href.endsWith('.png')); | ||
if (pngLinks.length) { | ||
return getLargestSizeIconUrl(pngLinks); | ||
} | ||
const icoIcon = links.filter(link => link.href.endsWith('.ico'))[0]; | ||
return (icoIcon === null || icoIcon === void 0 ? void 0 : icoIcon.href) || ''; | ||
} | ||
function getLargestSizeIconUrl(links) { | ||
const parsedLinks = links.map(parseIconLink); | ||
const maxSizeIcon = parsedLinks.sort((a, b) => (b.size > a.size ? 1 : -1))[0]; | ||
return (maxSizeIcon === null || maxSizeIcon === void 0 ? void 0 : maxSizeIcon.href) || ''; | ||
} | ||
function parseIconLink(link) { | ||
function getWebPageManifest() { | ||
var _a; | ||
if (!((_a = link.sizes) === null || _a === void 0 ? void 0 : _a.value)) { | ||
return { | ||
href: link.href, | ||
size: 0 | ||
}; | ||
const origin = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.location.origin; | ||
if (origin) { | ||
return origin + '/tonconnect-manifest.json'; | ||
} | ||
const sizes = Array.from(link.sizes) | ||
.map(size => { | ||
const groups = size.match(/(\d+)x(\d+)/i); | ||
if (!groups || !groups[1] || !groups[2]) { | ||
return undefined; | ||
} | ||
return parseInt(groups[1]) * parseInt(groups[2]); | ||
}) | ||
.filter(item => !!item); | ||
if (sizes.length === 0) { | ||
return { | ||
href: link.href, | ||
size: 0 | ||
}; | ||
} | ||
return { | ||
href: link.href, | ||
size: Math.max.apply(Math, sizes) | ||
}; | ||
return ''; | ||
} | ||
exports.getWebPageManifest = getWebPageManifest; |
{ | ||
"name": "@tonconnect/sdk", | ||
"version": "0.0.36", | ||
"version": "0.0.37", | ||
"scripts": { | ||
@@ -31,3 +31,3 @@ "build": "npx rimraf lib && ttsc && npx rimraf dist && webpack --mode development", | ||
"node-fetch": "^2.6.7", | ||
"@tonconnect/protocol": "^0.0.21" | ||
"@tonconnect/protocol": "^0.0.22" | ||
}, | ||
@@ -34,0 +34,0 @@ "files": [ |
103
README.md
@@ -18,2 +18,7 @@ # TON Connect SDK | ||
ℹ️ If you don't want auto-update the library, pass concrete version instead of `latest`, e.g. | ||
```html | ||
<script src="https://unpkg.com/@tonconnect/sdk@0.0.34/dist/tonconnect-sdk.min.js"></script> | ||
``` | ||
You can find `TonConnect` in global variable `TonConnectSDK`, e.g. | ||
@@ -29,3 +34,4 @@ ```html | ||
## Init connector and call autoConnect. If user connected his wallet before, connector will restore the connection | ||
# Usage | ||
## Init connector and call restoreConnection. If user connected his wallet before, connector will restore the connection | ||
@@ -40,2 +46,25 @@ ```ts | ||
## Add the tonconnect-manifest | ||
App needs to have its manifest to pass meta information to the wallet. Manifest is a JSON file named as `tonconnect-manifest.json` following format: | ||
```json | ||
{ | ||
"url": "<app-url>", // required | ||
"name": "<app-name>", // required | ||
"iconUrl": "<app-icon-url>", // required | ||
"termsOfUseUrl": "<terms-of-use-url>", // optional | ||
"privacyPolicyUrl": "<privacy-policy-url>" // optional | ||
} | ||
``` | ||
Best practice is to place the manifest in the root of your app, e.g. `https://myapp.com/tonconnect-manifest.json`. It allows the wallet to handle your app better and improve the UX connected to your app. | ||
Make sure that manifest is available to GET by its URL. | ||
[See details](https://github.com/ton-connect/docs/blob/main/requests-responses.md#app-manifest) | ||
If your manifest placed not in the root of your app, you can specify its path: | ||
```ts | ||
const connector = new TonConnect({ manifestUrl: 'https://myApp.com/assets/tonconnect-manifest.json' }); | ||
``` | ||
## Subscribe to the connection status changes | ||
@@ -99,3 +128,3 @@ ```js | ||
```ts | ||
if (!connetor.connected) { | ||
if (!connector.connected) { | ||
alert('Please connect wallet to send the transaction!'); | ||
@@ -121,3 +150,3 @@ } | ||
try { | ||
const result = await connetor.sendTransaction(transaction); | ||
const result = await connector.sendTransaction(transaction); | ||
@@ -135,1 +164,69 @@ // you can use signed boc to find the transaction | ||
``` | ||
# Backend authorization | ||
To authorize user in your backend with TonConnect you can use following schema: | ||
1. Fetch auth payload from your backend. It might be any random value. Backend must save information that this payload was sent to the client to check payload correctness later. | ||
2. Connect to the wallet when user clicks to the connection button: | ||
```ts | ||
connector.connect(walletConnectionSource, { tonProof: "<your-fetched-payload>" }); | ||
``` | ||
Note that you can use `tonProof` only with `connector.connect()` method. This feature is not available in `connector.restoreConnection()`. | ||
3. Read a signed result after user approves connection: | ||
```ts | ||
connector.onStatusChange(wallet => { | ||
if (!wallet) { | ||
return; | ||
} | ||
const tonProof = wallet.connectItems?.tonProof; | ||
if (tonProof) { | ||
if ('proof' in tonProof) { | ||
// send proo to your backend | ||
// e.g. myBackendCheckProof(tonProof.proof, wallet.account); | ||
return; | ||
} | ||
console.error(tonProof.error); | ||
} | ||
}); | ||
``` | ||
4. Send proof and user's account data to your backend. Backend should check the proof correctness and check that payload inside the proof was generated before. After all checks backend should return an auth token to the client. Notice that `Account` contains the `walletStateInit` property which can be helpful for your backend to get user's public key if user's wallet contract doesn't support corresponding get method. | ||
5. Client saves the auth token in the `localStorage` and use it to access to auth-required endpoints. Client should delete the token when user disconnects the wallet. | ||
[See an example of a dapp using backend authorization](https://github.com/ton-connect/demo-dapp-with-backend). | ||
[See an example of the dapp backend](https://github.com/ton-connect/demo-dapp-backend). | ||
# Use with NodeJS | ||
You can use the SDK in frontend apps and in backend apps created with NodeJS. | ||
## Installation | ||
`npm i @tonconnect/sdk` | ||
## Init connector | ||
When you use the SDK in backend, you have to pass `manifestUrl` and `IStorage` implementation to the TonConnect constructor. | ||
[See more about the manifest](##add-the-tonconnect-manifest). | ||
```ts | ||
import TonConnect from '@tonconnect/sdk'; | ||
const storage: IStorage = <your implementation of the IStorage> | ||
const connector = new TonConnect({ manifestUrl, storage }); | ||
``` | ||
Your storage should implement following interface: | ||
```ts | ||
export interface IStorage { | ||
setItem(key: string, value: string): Promise<void>; | ||
getItem(key: string): Promise<string | null>; | ||
removeItem(key: string): Promise<void>; | ||
} | ||
``` | ||
[See details about IStorage in the API documentation](https://ton-connect.github.io/sdk/interfaces/_tonconnect_sdk.IStorage.html). | ||
Other steps are the same as for browser apps. |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
124
2421
227
421104
+ Added@tonconnect/protocol@0.0.22(transitive)
- Removed@tonconnect/protocol@0.0.21(transitive)
Updated@tonconnect/protocol@^0.0.22