diff --git a/.env.example b/.env.example index b250edc..462926c 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +#### Bundle Vars + #### PRODUCTION PROD_IFRAME_URL=https://iframe.string-api.xyz PROD_API_URL=https://api.string-api.xyz @@ -17,4 +19,10 @@ LOCAL_API_URL=http://localhost:5555 VITE_ANALYTICS_LIB_PK= VITE_ANALYTICS_SUBDOMAIN_URL=https://metrics.string.xyz + +#### Test Page Vars + +VITE_IPFS_GATEWAY=https://nftstorage.link/ipfs/ +VITE_IPFS_CID=bafybeieqi56p6vlxofj6wkoort2m5r72ajhtikpzo53wnyze5isvn34fze VITE_STRING_API_KEY=str... + diff --git a/.prettierrc b/.prettierrc index 1299a71..ef9c443 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,11 +1,10 @@ { - "tabWidth": 4, - "useTabs": false, + "useTabs": true, "semi": true, "singleQuote": false, "trailingComma": "all", "bracketSpacing": true, - "jsxBracketSameLine": false, + "bracketSameLine": false, "arrowParens": "always", "printWidth": 160 } \ No newline at end of file diff --git a/README.md b/README.md index 5c67897..78ecef3 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,18 @@ npm i @stringpay/sdk yarn @stringpay/sdk ``` -Load the SDK's script on your app like so: +Load the SDK's script in the root of your app like so: ```HTML - + +``` + +Initialize the SDK in onMount (client side): +```JS +window.StringPay.init({ + env: "LOCAL", // Can be PROD, SANDBOX, DEV, or LOCAL + publicKey: apiKey, +}); ``` With this in place, add your `String Checkout` button anywhere you'd like: diff --git a/package.json b/package.json index 3322cd1..c8cc23e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@stringpay/sdk", - "version": "0.1.8", + "version": "0.2.0", "license": "UNLICENSED", "main": "./src/lib/index.ts", "types": "dist/index.d.ts", diff --git a/src/app.html b/src/app.html index a12d0c1..257b638 100644 --- a/src/app.html +++ b/src/app.html @@ -5,7 +5,7 @@ String SDK Test - + %sveltekit.head% diff --git a/src/lib/services/apiClient.service.ts b/src/lib/services/apiClient.service.ts index b5bc2a5..21f107f 100644 --- a/src/lib/services/apiClient.service.ts +++ b/src/lib/services/apiClient.service.ts @@ -9,6 +9,10 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien "Content-Type": "application/json", }; + const authHeaders: any = { + "X-Api-Key": apiKey, + } + const httpClient = axios.create({ baseURL: baseUrl, headers: commonHeaders, @@ -18,31 +22,15 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien const setWalletAddress = (addr: string) => (_userWalletAddress = addr); - async function createApiKey() { - const { data } = await httpClient.post<{ apiKey: string }>("/apikeys"); - return data; - } - - async function getApiKeys(limit = 10) { - const { data } = await httpClient.get("/apikeys", { - params: { limit }, - }); - return data; - } - - async function validateApiKey(keyId: string) { - const { data } = await httpClient.post<{ Status: string }>(`/apikeys/${keyId}/approve`); - return data; - } - async function requestLogin(walletAddress: string) { setWalletAddress(walletAddress); + try { - const headers = { "X-Api-Key": apiKey }; const { data } = await httpClient.get<{ nonce: string }>(`/login`, { params: { walletAddress: _userWalletAddress }, - headers, + headers: authHeaders, }); + return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -51,7 +39,6 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function createUser(nonce: string, signature: string, visitor?: VisitorData) { - const headers = { "X-Api-Key": apiKey }; const body = { nonce, signature, @@ -59,10 +46,9 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien }; try { - const { data } = await httpClient.post<{ - authToken: AuthToken; - user: User; - }>(`/users`, body, { headers }); + const { data } = await httpClient.post(`/users`, body, { + headers: authHeaders, + }); return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -71,20 +57,21 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function updateUser(userId: string, update: UserUpdate) { - const request = () => - httpClient.put(`/users/${userId}`, update, { - headers: { "X-Api-Key": apiKey }, - }); + try { + const request = () => httpClient.put(`/users/${userId}`, update); + const { data } = await authInterceptor<{ data: User }>(request); - const { data } = await authInterceptor<{ data: User }>(request); - return data; + return data; + } catch (e: any) { + const error = _getErrorFromAxiosError(e); + throw error; + } } async function requestEmailVerification(userId: string, email: string) { try { const request = () => httpClient.get(`/users/${userId}/verify-email`, { - headers: { "X-Api-Key": apiKey }, params: { email }, // timeout: 15 * 60 * 1000 // 15 minutes }); @@ -97,18 +84,18 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function loginUser(nonce: string, signature: string, visitor?: VisitorData, bypassDeviceCheck = false) { - const headers = { "X-Api-Key": apiKey }; const body = { nonce, signature, fingerprint: visitor, }; + const bypassDevice = bypassDeviceCheck ? "?bypassDevice=true" : ""; + try { - const { data } = await httpClient.post<{ - authToken: AuthToken; - user: User; - }>(`/login/sign${bypassDeviceCheck ? "?bypassDevice=true" : ""}`, body, { headers }); + const { data } = await httpClient.post(`/login/sign${bypassDevice}`, body, { + headers: authHeaders, + }); return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -117,13 +104,12 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function refreshToken(walletAddress: string) { - const headers = { "X-Api-Key": apiKey }; try { - const { data } = await httpClient.post<{ - authToken: AuthToken; - user: User; - }>(`/login/refresh`, { walletAddress }, { headers }); - console.log(" - Token was refreshed"); + const { data } = await httpClient.post(`/login/refresh`, { walletAddress }, { + headers: authHeaders, + }); + console.debug(" - Token was refreshed"); + return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -132,11 +118,9 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function logoutUser() { - const headers = { "X-Api-Key": apiKey }; try { - const { status } = await httpClient.post(`/login/logout`, {}, { headers }); - if (status === 204) return; - else throw new Error("logout failed"); + const { status } = await httpClient.post(`/login/logout`); + if (status !== 204) throw new Error("logout failed"); } catch (e: any) { const error = _getErrorFromAxiosError(e); throw error; @@ -144,13 +128,12 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function getUserStatus(userId: string) { - if (!userId) throw new Error("userId is required"); - const headers = { "X-Api-Key": apiKey }; try { - const request = () => httpClient.get(`/users/${userId}/status`, { headers }); + const request = () => httpClient.get(`/users/${userId}/status`); const { data } = await authInterceptor<{ data: { status: string }; }>(request); + return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -159,10 +142,10 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function getQuote(payload: QuoteRequestPayload) { - const headers = { "X-Api-Key": apiKey }; try { - const request = () => httpClient.post(`/quotes`, payload, { headers }); + const request = () => httpClient.post(`/quotes`, payload); const { data } = await authInterceptor<{ data: TransactPayload }>(request); + return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -171,12 +154,12 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } async function transact(transactPayload: TransactPayload) { - const headers = { "X-Api-Key": apiKey }; try { - const request = () => httpClient.post(`/transactions`, transactPayload, { headers }); + const request = () => httpClient.post(`/transactions`, transactPayload); const { data } = await authInterceptor<{ data: TransactionResponse; }>(request); + return data; } catch (e: any) { const error = _getErrorFromAxiosError(e); @@ -215,9 +198,6 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } return { - createApiKey, - getApiKeys, - validateApiKey, requestLogin, createUser, updateUser, @@ -233,15 +213,12 @@ export function createApiClient({ baseUrl, apiKey }: ApiClientOptions): ApiClien } export interface ApiClient { - createApiKey: () => Promise<{ apiKey: string }>; - getApiKeys: () => Promise; - validateApiKey: (keyId: string) => Promise<{ Status: string }>; requestLogin: (walletAddress: string) => Promise<{ nonce: string }>; - createUser: (nonce: string, signature: string, visitor?: VisitorData) => Promise<{ authToken: AuthToken; user: User }>; + createUser: (nonce: string, signature: string, visitor?: VisitorData) => Promise; updateUser: (userId: string, userUpdate: UserUpdate) => Promise; requestEmailVerification: (userId: string, email: string) => Promise; - loginUser: (nonce: string, signature: string, visitor?: VisitorData, bypassDeviceCheck?: boolean) => Promise<{ authToken: AuthToken; user: User }>; - refreshToken: (walletAddress: string) => Promise<{ authToken: AuthToken; user: User }>; + loginUser: (nonce: string, signature: string, visitor?: VisitorData, bypassDeviceCheck?: boolean) => Promise; + refreshToken: (walletAddress: string) => Promise; logoutUser: () => Promise; getUserStatus: (userId: string) => Promise<{ status: string }>; getQuote: (payload: QuoteRequestPayload) => Promise; @@ -249,15 +226,6 @@ export interface ApiClient { setWalletAddress: (walletAddress: string) => void; } -interface ApiKeyResponse { - id: string; - status: string; - authType: string; - data: string; - createdAt: string; - updatedAt: string; -} - interface RefreshToken { token: string; expAt: Date; @@ -270,6 +238,11 @@ interface AuthToken { expAt: string; } +export interface AuthResponse { + authToken: AuthToken; + user: User; +} + export interface UserUpdate { walletAddress?: string; firstName?: string; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1cd77b3..ad98bb5 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,21 +4,25 @@ import { writable } from "svelte/store"; import { ethers } from "ethers"; - const apiKey = import.meta.env.VITE_STRING_API_KEY; - const signerAddress = writable(""); + const STR_API_KEY = import.meta.env.VITE_STRING_API_KEY; + + const IPFS_GATEWAY = import.meta.env.VITE_IPFS_GATEWAY + const IPFS_CID = import.meta.env.VITE_IPFS_CID + + const STR_NFT_SRC = `${IPFS_GATEWAY}${IPFS_CID}/Demo_Character_1.png` + $: payload = { - name: "String Demo NFT", + name: "String Test NFT [AVAX]", collection: "String Demo", - imageSrc: - "https://gateway.pinata.cloud/ipfs/bafybeibtmy26mac47n5pp6srds76h74riqs76erw24p5yvdhmwu7pxlcx4/STR_Logo_1.png", - imageAlt: "NFT", + imageSrc: STR_NFT_SRC, + imageAlt: "String NFT", currency: "AVAX", price: 0.08, chainID: 43113, userAddress: $signerAddress, - contractAddress: "0x41e11fF9F71f51800F67cb913eA6Bc59d3F126Aa", + contractAddress: "0xea1ffe2cf6630a20e1ba397e95358daf362c8781", contractFunction: "mintTo(address)", contractReturn: "uint256", contractParameters: [$signerAddress], @@ -34,7 +38,7 @@ window.StringPay.init({ env: "LOCAL", - publicKey: apiKey + publicKey: STR_API_KEY, });