@tiplink/wallet-adapter
Advanced tools
Comparing version 0.1.7 to 0.1.8
@@ -36,3 +36,3 @@ "use strict"; | ||
const wallet_standard_util_1 = require("@solana/wallet-standard-util"); | ||
const iframePath = "frame"; | ||
const iframePath = ""; | ||
const READY_SIGNAL_INTERVAL_MS = 250; | ||
@@ -180,2 +180,14 @@ // preload for iframe doesn't work https://bugs.chromium.org/p/chromium/issues/detail?id=593267 | ||
} | ||
getTipLinkLogoUrl() { | ||
const logoUrl = new URL("adapter-tiplink-logo.svg", (0, utils_js_1.getTipLinkUrl)(this.buildEnv)); | ||
return logoUrl.toString(); | ||
} | ||
getGoogleLogoUrl() { | ||
const logoUrl = new URL("adapter-google-logo.svg", (0, utils_js_1.getTipLinkUrl)(this.buildEnv)); | ||
return logoUrl.toString(); | ||
} | ||
getBackgroundImageUrl() { | ||
const logoUrl = new URL("adapter-modal-background.png", (0, utils_js_1.getTipLinkUrl)(this.buildEnv)); | ||
return logoUrl.toString(); | ||
} | ||
fadeIn(element) { | ||
@@ -233,2 +245,62 @@ element.classList.remove("fade-out"); | ||
} | ||
_createDirectLoginModal(onClick, onClose) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const modal = (0, embedUtils_js_1.htmlToElement)("<div id='tipLinkAlertModal'></div>"); | ||
const innerContainer = (0, embedUtils_js_1.htmlToElement)(`<div id='tipLinkAlert__inner_container' style="background-image: url(${this.getBackgroundImageUrl()}); background-color: #F2F8FC; background-repeat: no-repeat; background-position: center; background-size: cover"></div>`); | ||
const overlay = (0, embedUtils_js_1.htmlToElement)("<div id='tipLinkAlert__modal_overlay'></div>"); | ||
const tipLinkAlert = (0, embedUtils_js_1.htmlToElement)('<div id="tipLinkAlert" class="tipLink-alert--v2"></div>'); | ||
const tipLinkLoginContainer = (0, embedUtils_js_1.htmlToElement)(`<div id="tipLinkAlert__login_container">` + | ||
`<img src="${this.getTipLinkLogoUrl()}" id="tipLinkAlert__login_tiplink_logo"/>` + | ||
`<div id="tipLinkAlert__login_title">${"TipLink: the world's simplest wallet"}</div>` + | ||
`<div id="tipLinkAlert__login_desc1">${"Login/create your TipLink wallet with just 2 clicks."}</div>` + | ||
`<div id="tipLinkAlert__login_desc2">${"You'll be asked to sign in securely with Solana after logging in."}</div>` + | ||
"</div>"); | ||
const tipLinkLoginButton = (0, embedUtils_js_1.htmlToElement)(`<div id="tipLinkAlert__login_btn">` + | ||
`<div id="tipLinkAlert__google_logo_container"><img src="${this.getGoogleLogoUrl()}" id="tipLinkAlert__google_logo"/></div>` + | ||
`<p id="tipLinkAlert_continue_with_google">${"Continue with Google"}</p>` + | ||
`</div>`); | ||
const closeButtonIconUrl = this.getCloseButtonUrl(); | ||
const closeButton = (0, embedUtils_js_1.htmlToElement)(`<div id="tipLinkAlert__close-btn"><img id="tipLinkAlert__close-btn-image" src="${closeButtonIconUrl}"/></div>`); | ||
tipLinkLoginContainer.appendChild(tipLinkLoginButton); | ||
tipLinkAlert.appendChild(tipLinkLoginContainer); | ||
innerContainer.appendChild(tipLinkAlert); | ||
innerContainer.appendChild(closeButton); | ||
modal.appendChild(innerContainer); | ||
modal.appendChild(overlay); | ||
const removePopupBlockedAlert = () => { | ||
modal.remove(); | ||
if (this.tipLinkAlertContainer && | ||
this.tipLinkAlertContainer.children.length === 0) { | ||
this.tipLinkAlertContainer.style.display = "none"; | ||
} | ||
}; | ||
const bindOnLoad = () => { | ||
tipLinkLoginButton.addEventListener("click", () => { | ||
onClick(); | ||
removePopupBlockedAlert(); | ||
}); | ||
}; | ||
const bindCloseButton = () => { | ||
closeButton.addEventListener("click", () => { | ||
removePopupBlockedAlert(); | ||
onClose(); | ||
}); | ||
overlay.addEventListener("mousedown", () => { | ||
removePopupBlockedAlert(); | ||
onClose(); | ||
}); | ||
}; | ||
const attachOnLoad = () => { | ||
if (this.tipLinkAlertContainer) { | ||
this.tipLinkAlertContainer.appendChild(modal); | ||
} | ||
}; | ||
attachOnLoad(); | ||
bindCloseButton(); | ||
bindOnLoad(); | ||
if (this.tipLinkAlertContainer) { | ||
this.tipLinkAlertContainer.style.display = "block"; | ||
} | ||
}); | ||
} | ||
_createPopupBlockAlert(onClick, onClose, popupType) { | ||
@@ -310,3 +382,3 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
postReady(windowParams) { | ||
postReady(windowParams, checkAllowlist = true) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -321,7 +393,12 @@ let interval = undefined; | ||
clearInterval(interval); | ||
const timeout = setTimeout(() => { | ||
this._createPopupBlockAlert(() => undefined, () => undefined, PopupType.NOT_ALLOWLISTED); | ||
console.error("This application has not been allowlisted for the TipLink Wallet Adapter. Please reach out to contact@tiplink.io for support."); | ||
}, NOT_ALLOWLISTED_TIMEOUT_MS); | ||
resolve(timeout); | ||
if (checkAllowlist) { | ||
const timeout = setTimeout(() => { | ||
this._createPopupBlockAlert(() => undefined, () => undefined, PopupType.NOT_ALLOWLISTED); | ||
console.error("This application has not been allowlisted for the TipLink Wallet Adapter. Please reach out to contact@tiplink.io for support."); | ||
}, NOT_ALLOWLISTED_TIMEOUT_MS); | ||
resolve(timeout); | ||
} | ||
else { | ||
resolve(undefined); | ||
} | ||
}), | ||
@@ -346,9 +423,15 @@ }, | ||
} | ||
init(directConnect, autoConnect) { | ||
init({ directConnect, autoConnect, siwsInput, }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let windowParams = undefined; | ||
let siwsLoginPopupBlocked = false; | ||
if (directConnect) { | ||
windowParams = this.windowCommunicator.openPopup("/adapter_login?forceLogin=true&isDirect=true"); | ||
windowParams = this.windowCommunicator.openPopup(`/adapter_login?forceLogin=true&isDirect=true${siwsInput ? "&isSiws=true" : ""}`); | ||
if (!windowParams.popup || windowParams.popup.closed) { | ||
directConnect = false; | ||
if (!siwsInput) { | ||
directConnect = false; | ||
} | ||
else { | ||
siwsLoginPopupBlocked = true; | ||
} | ||
} | ||
@@ -375,19 +458,23 @@ } | ||
this.styleLink = (0, embedUtils_js_1.htmlToElement)(`<link href="${cssLink.toString()}" rel="stylesheet" type="text/css">`); | ||
const ogListener = (event) => { | ||
const { data } = event; | ||
console.log("received message", data); | ||
if (data.type === "loaded") { | ||
const { publicKey } = data; | ||
this.publicKeyString = publicKey; | ||
this.hideIframe(); | ||
} | ||
}; | ||
window.addEventListener("message", ogListener); | ||
let ogListener = undefined; | ||
if (!directConnect) { | ||
ogListener = (event) => { | ||
const { data } = event; | ||
console.log("received message", data); | ||
if (data.type === "loaded") { | ||
const { publicKey } = data; | ||
this.publicKeyString = publicKey; | ||
this.hideIframe(); | ||
} | ||
}; | ||
window.addEventListener("message", ogListener); | ||
} | ||
this.tipLinkAlertContainer = (0, embedUtils_js_1.htmlToElement)(`<div id="tipLinkAlertContainer" style="display:none; z-index: 100998"></div>`); | ||
this.tipLinkToastContainer = (0, embedUtils_js_1.htmlToElement)(`<div id="tipLinkToastContainer" style="display:none; z-index: 100999"></div>`); | ||
let windowClosedInterval = undefined; | ||
let iFrameHandshakeEnded = false; | ||
const iFrameHandshakeEnded = false; | ||
const handleSetup = () => __awaiter(this, void 0, void 0, function* () { | ||
return new Promise((resolve, reject) => { | ||
console.log("actually RUNNING handle setup"); | ||
const fnsAtEnd = []; | ||
try { | ||
@@ -412,2 +499,3 @@ if (this.tipLinkIframe === undefined) { | ||
let errorTimeout = undefined; | ||
let iFrameHandshakeEnded = false; | ||
this.tipLinkIframe.addEventListener("load", () => __awaiter(this, void 0, void 0, function* () { | ||
@@ -424,2 +512,3 @@ if (!this.tipLinkIframe) { | ||
} | ||
const interval = undefined; | ||
const { close: closeIframeChannel } = this.windowCommunicator.setupHandshakeWithIframe(this.tipLinkIframe, { | ||
@@ -445,3 +534,26 @@ loaded: { | ||
} | ||
resolve(publicKey); | ||
console.log("triggered loaded!"); | ||
let siwsOutput = undefined; | ||
if (siwsInput && windowParams) { | ||
console.log("setting up signin", siwsInput, windowParams); | ||
try { | ||
console.log("CALLING sign in from callback"); | ||
siwsOutput = yield this.signIn(siwsInput, windowParams); | ||
} | ||
catch (err) { | ||
reject(err); | ||
} | ||
} | ||
else if (!windowParams) { | ||
console.error("windowParams is empty!"); | ||
} | ||
console.log("publicKey", publicKey, "siwsOutput", siwsOutput); | ||
clearInterval(interval); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
resolve({ | ||
pk: publicKey, | ||
siwsOutput, | ||
}); | ||
}), | ||
@@ -460,2 +572,7 @@ }, | ||
this.cleanUp(); | ||
clearInterval(interval); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via cLOSED"); | ||
reject(); | ||
@@ -465,3 +582,6 @@ }), | ||
}, ["loaded", "closed"]); | ||
window.removeEventListener("message", ogListener); | ||
fnsAtEnd.push(closeIframeChannel); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
if (directConnect) { | ||
@@ -493,7 +613,24 @@ if ((windowParams === null || windowParams === void 0 ? void 0 : windowParams.popup) && !(windowParams === null || windowParams === void 0 ? void 0 : windowParams.popup.closed)) { | ||
} | ||
else if (siwsLoginPopupBlocked) { | ||
// show popup dialog, | ||
// if user clicks to not open dialog, make sure to reject | ||
this._createDirectLoginModal(() => { | ||
windowParams = this.windowCommunicator.openPopup(`/adapter_login?forceLogin=true&isDirect=true${siwsInput ? "&isSiws=true" : ""}`); | ||
this.postReady(windowParams, false); | ||
}, () => { | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via dialog closed"); | ||
closeIframeChannel(); | ||
reject(); | ||
}); | ||
} | ||
else { | ||
reject(new Error("window is closed")); | ||
reject(new Error("window is closed early")); | ||
} | ||
} | ||
if (this.publicKeyString) { | ||
// if the og listener above triggered we would have detected the public key | ||
// saved from the iframe from a previous session | ||
this.hideIframe(); | ||
@@ -505,3 +642,9 @@ closeIframeChannel(); | ||
} | ||
resolve(this.publicKeyString); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("resolved saved public key from iframe"); | ||
resolve({ | ||
pk: this.publicKeyString, | ||
}); | ||
} | ||
@@ -512,4 +655,11 @@ })); | ||
console.log("REJECTING error", error); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via errior"); | ||
reject(error); | ||
} | ||
finally { | ||
fnsAtEnd.forEach((fn) => fn()); | ||
} | ||
}); | ||
@@ -691,11 +841,11 @@ }); | ||
} | ||
_signMessage(message, path) { | ||
_signMessage(message, path, windowOpenParams) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return new Promise((resolve, reject) => { | ||
this.extendSession(); | ||
void this.windowCommunicator | ||
.setupHandshakeWithPath(path, { | ||
const cbs = { | ||
loaded: { | ||
type: window_js_1.CallbackType.POST, | ||
cb: () => __awaiter(this, void 0, void 0, function* () { | ||
console.log("triggered loaded on sign message, posting message", message); | ||
return { | ||
@@ -733,6 +883,20 @@ message: Buffer.from(message).toString("base64"), | ||
}, | ||
}, ["signed_message", "closed", "accountChanged"], PopupType.MESSAGE, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
}; | ||
const endSignals = ["signed_message", "closed", "accountChanged"]; | ||
const popupType = PopupType.MESSAGE; | ||
if (windowOpenParams) { | ||
console.log("window open params setting up handshake"); | ||
this.windowCommunicator | ||
.setupHandshakeWithWindowParams(windowOpenParams, cbs, endSignals, popupType, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
} | ||
else { | ||
this.windowCommunicator | ||
.setupHandshakeWithPath(path, cbs, endSignals, popupType, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
} | ||
}); | ||
@@ -746,3 +910,3 @@ }); | ||
} | ||
signIn(input) { | ||
signIn(input, windowOpenParams) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -759,3 +923,3 @@ const publicKeyAddress = (input === null || input === void 0 ? void 0 : input.address) || this.publicKeyString; | ||
const signInMessage = (0, wallet_standard_util_1.createSignInMessage)(siwsRequiredFields); | ||
const signature = yield this._signMessage(signInMessage, "sign_in_with_solana"); | ||
const signature = yield this._signMessage(signInMessage, "sign_in_with_solana", windowOpenParams); | ||
return { | ||
@@ -762,0 +926,0 @@ account: { |
@@ -82,3 +82,3 @@ "use strict"; | ||
} | ||
_connect(onPublicKeyConnected, autoConnect = false) { | ||
_connect({ forceNoDirectConnect, siwsInput, autoConnect = false, }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -88,2 +88,3 @@ console.log("BEGIN: connecting status for iden", this.connecting, this._iden); | ||
return; | ||
let solanaSignInOutput; | ||
this._disconnected = false; | ||
@@ -115,4 +116,10 @@ try { | ||
try { | ||
publicKey = new web3_js_1.PublicKey(yield wallet.init(autoConnect ? false : this._directConnect, autoConnect)); | ||
console.log("DONE WALLET INIT!! connecting status right now is", this._connecting); | ||
const { pk, siwsOutput } = yield wallet.init({ | ||
directConnect: forceNoDirectConnect ? false : this._directConnect, | ||
autoConnect, | ||
siwsInput, | ||
}); | ||
publicKey = new web3_js_1.PublicKey(pk); | ||
solanaSignInOutput = siwsOutput; | ||
console.log("DONE WALLET INIT!! connecting status right now is", this._connecting, "disconnected", this._disconnected, "public key", pk, "siws output", siwsOutput); | ||
} | ||
@@ -129,5 +136,3 @@ catch (error) { | ||
this._publicKey = publicKey; | ||
if (onPublicKeyConnected) { | ||
onPublicKeyConnected(publicKey); | ||
} | ||
this.emit("connect", publicKey); | ||
console.log("FINISHED connecting"); | ||
@@ -145,2 +150,5 @@ // console.log("adapter.connect, connected"); | ||
} | ||
return { | ||
siwsOutput: solanaSignInOutput, | ||
}; | ||
}); | ||
@@ -150,5 +158,6 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this._connect((publicKey) => { | ||
this.emit("connect", publicKey); | ||
}, true); | ||
this._connect({ | ||
forceNoDirectConnect: true, | ||
}); | ||
return; | ||
}); | ||
@@ -158,5 +167,4 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this._connect((publicKey) => { | ||
this.emit("connect", publicKey); | ||
}); | ||
this._connect({}); | ||
return; | ||
}); | ||
@@ -168,2 +176,3 @@ } | ||
this._connecting = false; | ||
console.log("triggered disconnected!"); | ||
this._disconnected = true; | ||
@@ -274,7 +283,15 @@ if (wallet) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
console.log("triggering sign in!"); | ||
try { | ||
let wasConnected = true; | ||
if (!this.connected) { | ||
wasConnected = false; | ||
yield this._connect(); | ||
const output = yield this._connect({ | ||
siwsInput: input, | ||
}); | ||
const siwsOutput = output === null || output === void 0 ? void 0 : output.siwsOutput; | ||
if (input) { | ||
if (!siwsOutput) { | ||
throw new Error("No Solana Sign In Output"); | ||
} | ||
return siwsOutput; | ||
} | ||
} | ||
@@ -289,5 +306,2 @@ const wallet = this._wallet; | ||
const siwsOutput = yield wallet.signIn(input); | ||
if (!wasConnected) { | ||
this.emit("connect", publicKey); | ||
} | ||
return siwsOutput; | ||
@@ -294,0 +308,0 @@ } |
@@ -11,3 +11,3 @@ "use strict"; | ||
case "development": | ||
return "https://dev.tiplink.io"; | ||
return "https://alex-devel.tiplink.io"; | ||
case "adapter": | ||
@@ -14,0 +14,0 @@ return "https://adapter.tiplink.io"; |
@@ -52,3 +52,7 @@ "use strict"; | ||
} | ||
const { type, cb: callback } = windowCallbacks[event.data.type]; | ||
const windowCallback = windowCallbacks[event.data.type]; | ||
if (!windowCallback) { | ||
return; | ||
} | ||
const { type, cb: callback } = windowCallback; | ||
if (endSignalsSet.has(event.data.type)) { | ||
@@ -116,4 +120,3 @@ endFn === null || endFn === void 0 ? void 0 : endFn(); | ||
checkPopupClosed = setInterval(function () { | ||
console.log("STILL CHECKING 2"); | ||
if (popup.closed) { | ||
if (!popup || popup.closed) { | ||
clearInterval(checkPopupClosed); | ||
@@ -134,3 +137,2 @@ upperReject("User closed popup"); | ||
checkPopupClosed = setInterval(function () { | ||
console.log("STILL CHECKING 1"); | ||
if (popup.closed) { | ||
@@ -137,0 +139,0 @@ clearInterval(checkPopupClosed); |
@@ -13,3 +13,3 @@ /* | ||
import { createSignInMessage, } from "@solana/wallet-standard-util"; | ||
const iframePath = "frame"; | ||
const iframePath = ""; | ||
const READY_SIGNAL_INTERVAL_MS = 250; | ||
@@ -149,2 +149,14 @@ // preload for iframe doesn't work https://bugs.chromium.org/p/chromium/issues/detail?id=593267 | ||
} | ||
getTipLinkLogoUrl() { | ||
const logoUrl = new URL("adapter-tiplink-logo.svg", getTipLinkUrl(this.buildEnv)); | ||
return logoUrl.toString(); | ||
} | ||
getGoogleLogoUrl() { | ||
const logoUrl = new URL("adapter-google-logo.svg", getTipLinkUrl(this.buildEnv)); | ||
return logoUrl.toString(); | ||
} | ||
getBackgroundImageUrl() { | ||
const logoUrl = new URL("adapter-modal-background.png", getTipLinkUrl(this.buildEnv)); | ||
return logoUrl.toString(); | ||
} | ||
fadeIn(element) { | ||
@@ -202,2 +214,60 @@ element.classList.remove("fade-out"); | ||
} | ||
async _createDirectLoginModal(onClick, onClose) { | ||
const modal = htmlToElement("<div id='tipLinkAlertModal'></div>"); | ||
const innerContainer = htmlToElement(`<div id='tipLinkAlert__inner_container' style="background-image: url(${this.getBackgroundImageUrl()}); background-color: #F2F8FC; background-repeat: no-repeat; background-position: center; background-size: cover"></div>`); | ||
const overlay = htmlToElement("<div id='tipLinkAlert__modal_overlay'></div>"); | ||
const tipLinkAlert = htmlToElement('<div id="tipLinkAlert" class="tipLink-alert--v2"></div>'); | ||
const tipLinkLoginContainer = htmlToElement(`<div id="tipLinkAlert__login_container">` + | ||
`<img src="${this.getTipLinkLogoUrl()}" id="tipLinkAlert__login_tiplink_logo"/>` + | ||
`<div id="tipLinkAlert__login_title">${"TipLink: the world's simplest wallet"}</div>` + | ||
`<div id="tipLinkAlert__login_desc1">${"Login/create your TipLink wallet with just 2 clicks."}</div>` + | ||
`<div id="tipLinkAlert__login_desc2">${"You'll be asked to sign in securely with Solana after logging in."}</div>` + | ||
"</div>"); | ||
const tipLinkLoginButton = htmlToElement(`<div id="tipLinkAlert__login_btn">` + | ||
`<div id="tipLinkAlert__google_logo_container"><img src="${this.getGoogleLogoUrl()}" id="tipLinkAlert__google_logo"/></div>` + | ||
`<p id="tipLinkAlert_continue_with_google">${"Continue with Google"}</p>` + | ||
`</div>`); | ||
const closeButtonIconUrl = this.getCloseButtonUrl(); | ||
const closeButton = htmlToElement(`<div id="tipLinkAlert__close-btn"><img id="tipLinkAlert__close-btn-image" src="${closeButtonIconUrl}"/></div>`); | ||
tipLinkLoginContainer.appendChild(tipLinkLoginButton); | ||
tipLinkAlert.appendChild(tipLinkLoginContainer); | ||
innerContainer.appendChild(tipLinkAlert); | ||
innerContainer.appendChild(closeButton); | ||
modal.appendChild(innerContainer); | ||
modal.appendChild(overlay); | ||
const removePopupBlockedAlert = () => { | ||
modal.remove(); | ||
if (this.tipLinkAlertContainer && | ||
this.tipLinkAlertContainer.children.length === 0) { | ||
this.tipLinkAlertContainer.style.display = "none"; | ||
} | ||
}; | ||
const bindOnLoad = () => { | ||
tipLinkLoginButton.addEventListener("click", () => { | ||
onClick(); | ||
removePopupBlockedAlert(); | ||
}); | ||
}; | ||
const bindCloseButton = () => { | ||
closeButton.addEventListener("click", () => { | ||
removePopupBlockedAlert(); | ||
onClose(); | ||
}); | ||
overlay.addEventListener("mousedown", () => { | ||
removePopupBlockedAlert(); | ||
onClose(); | ||
}); | ||
}; | ||
const attachOnLoad = () => { | ||
if (this.tipLinkAlertContainer) { | ||
this.tipLinkAlertContainer.appendChild(modal); | ||
} | ||
}; | ||
attachOnLoad(); | ||
bindCloseButton(); | ||
bindOnLoad(); | ||
if (this.tipLinkAlertContainer) { | ||
this.tipLinkAlertContainer.style.display = "block"; | ||
} | ||
} | ||
async _createPopupBlockAlert(onClick, onClose, popupType) { | ||
@@ -277,3 +347,3 @@ const modal = htmlToElement("<div id='tipLinkAlertModal'></div>"); | ||
} | ||
async postReady(windowParams) { | ||
async postReady(windowParams, checkAllowlist = true) { | ||
let interval = undefined; | ||
@@ -287,7 +357,12 @@ return new Promise((resolve, reject) => { | ||
clearInterval(interval); | ||
const timeout = setTimeout(() => { | ||
this._createPopupBlockAlert(() => undefined, () => undefined, PopupType.NOT_ALLOWLISTED); | ||
console.error("This application has not been allowlisted for the TipLink Wallet Adapter. Please reach out to contact@tiplink.io for support."); | ||
}, NOT_ALLOWLISTED_TIMEOUT_MS); | ||
resolve(timeout); | ||
if (checkAllowlist) { | ||
const timeout = setTimeout(() => { | ||
this._createPopupBlockAlert(() => undefined, () => undefined, PopupType.NOT_ALLOWLISTED); | ||
console.error("This application has not been allowlisted for the TipLink Wallet Adapter. Please reach out to contact@tiplink.io for support."); | ||
}, NOT_ALLOWLISTED_TIMEOUT_MS); | ||
resolve(timeout); | ||
} | ||
else { | ||
resolve(undefined); | ||
} | ||
}, | ||
@@ -311,8 +386,14 @@ }, | ||
} | ||
async init(directConnect, autoConnect) { | ||
async init({ directConnect, autoConnect, siwsInput, }) { | ||
let windowParams = undefined; | ||
let siwsLoginPopupBlocked = false; | ||
if (directConnect) { | ||
windowParams = this.windowCommunicator.openPopup("/adapter_login?forceLogin=true&isDirect=true"); | ||
windowParams = this.windowCommunicator.openPopup(`/adapter_login?forceLogin=true&isDirect=true${siwsInput ? "&isSiws=true" : ""}`); | ||
if (!windowParams.popup || windowParams.popup.closed) { | ||
directConnect = false; | ||
if (!siwsInput) { | ||
directConnect = false; | ||
} | ||
else { | ||
siwsLoginPopupBlocked = true; | ||
} | ||
} | ||
@@ -339,19 +420,23 @@ } | ||
this.styleLink = htmlToElement(`<link href="${cssLink.toString()}" rel="stylesheet" type="text/css">`); | ||
const ogListener = (event) => { | ||
const { data } = event; | ||
console.log("received message", data); | ||
if (data.type === "loaded") { | ||
const { publicKey } = data; | ||
this.publicKeyString = publicKey; | ||
this.hideIframe(); | ||
} | ||
}; | ||
window.addEventListener("message", ogListener); | ||
let ogListener = undefined; | ||
if (!directConnect) { | ||
ogListener = (event) => { | ||
const { data } = event; | ||
console.log("received message", data); | ||
if (data.type === "loaded") { | ||
const { publicKey } = data; | ||
this.publicKeyString = publicKey; | ||
this.hideIframe(); | ||
} | ||
}; | ||
window.addEventListener("message", ogListener); | ||
} | ||
this.tipLinkAlertContainer = htmlToElement(`<div id="tipLinkAlertContainer" style="display:none; z-index: 100998"></div>`); | ||
this.tipLinkToastContainer = htmlToElement(`<div id="tipLinkToastContainer" style="display:none; z-index: 100999"></div>`); | ||
let windowClosedInterval = undefined; | ||
let iFrameHandshakeEnded = false; | ||
const iFrameHandshakeEnded = false; | ||
const handleSetup = async () => { | ||
return new Promise((resolve, reject) => { | ||
console.log("actually RUNNING handle setup"); | ||
const fnsAtEnd = []; | ||
try { | ||
@@ -376,2 +461,3 @@ if (this.tipLinkIframe === undefined) { | ||
let errorTimeout = undefined; | ||
let iFrameHandshakeEnded = false; | ||
this.tipLinkIframe.addEventListener("load", async () => { | ||
@@ -388,2 +474,3 @@ if (!this.tipLinkIframe) { | ||
} | ||
const interval = undefined; | ||
const { close: closeIframeChannel } = this.windowCommunicator.setupHandshakeWithIframe(this.tipLinkIframe, { | ||
@@ -409,3 +496,26 @@ loaded: { | ||
} | ||
resolve(publicKey); | ||
console.log("triggered loaded!"); | ||
let siwsOutput = undefined; | ||
if (siwsInput && windowParams) { | ||
console.log("setting up signin", siwsInput, windowParams); | ||
try { | ||
console.log("CALLING sign in from callback"); | ||
siwsOutput = await this.signIn(siwsInput, windowParams); | ||
} | ||
catch (err) { | ||
reject(err); | ||
} | ||
} | ||
else if (!windowParams) { | ||
console.error("windowParams is empty!"); | ||
} | ||
console.log("publicKey", publicKey, "siwsOutput", siwsOutput); | ||
clearInterval(interval); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
resolve({ | ||
pk: publicKey, | ||
siwsOutput, | ||
}); | ||
}, | ||
@@ -424,2 +534,7 @@ }, | ||
this.cleanUp(); | ||
clearInterval(interval); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via cLOSED"); | ||
reject(); | ||
@@ -429,3 +544,6 @@ }, | ||
}, ["loaded", "closed"]); | ||
window.removeEventListener("message", ogListener); | ||
fnsAtEnd.push(closeIframeChannel); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
if (directConnect) { | ||
@@ -457,7 +575,24 @@ if (windowParams?.popup && !windowParams?.popup.closed) { | ||
} | ||
else if (siwsLoginPopupBlocked) { | ||
// show popup dialog, | ||
// if user clicks to not open dialog, make sure to reject | ||
this._createDirectLoginModal(() => { | ||
windowParams = this.windowCommunicator.openPopup(`/adapter_login?forceLogin=true&isDirect=true${siwsInput ? "&isSiws=true" : ""}`); | ||
this.postReady(windowParams, false); | ||
}, () => { | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via dialog closed"); | ||
closeIframeChannel(); | ||
reject(); | ||
}); | ||
} | ||
else { | ||
reject(new Error("window is closed")); | ||
reject(new Error("window is closed early")); | ||
} | ||
} | ||
if (this.publicKeyString) { | ||
// if the og listener above triggered we would have detected the public key | ||
// saved from the iframe from a previous session | ||
this.hideIframe(); | ||
@@ -469,3 +604,9 @@ closeIframeChannel(); | ||
} | ||
resolve(this.publicKeyString); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("resolved saved public key from iframe"); | ||
resolve({ | ||
pk: this.publicKeyString, | ||
}); | ||
} | ||
@@ -476,4 +617,11 @@ }); | ||
console.log("REJECTING error", error); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via errior"); | ||
reject(error); | ||
} | ||
finally { | ||
fnsAtEnd.forEach((fn) => fn()); | ||
} | ||
}); | ||
@@ -642,10 +790,10 @@ }; | ||
} | ||
async _signMessage(message, path) { | ||
async _signMessage(message, path, windowOpenParams) { | ||
return new Promise((resolve, reject) => { | ||
this.extendSession(); | ||
void this.windowCommunicator | ||
.setupHandshakeWithPath(path, { | ||
const cbs = { | ||
loaded: { | ||
type: CallbackType.POST, | ||
cb: async () => { | ||
console.log("triggered loaded on sign message, posting message", message); | ||
return { | ||
@@ -683,6 +831,20 @@ message: Buffer.from(message).toString("base64"), | ||
}, | ||
}, ["signed_message", "closed", "accountChanged"], PopupType.MESSAGE, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
}; | ||
const endSignals = ["signed_message", "closed", "accountChanged"]; | ||
const popupType = PopupType.MESSAGE; | ||
if (windowOpenParams) { | ||
console.log("window open params setting up handshake"); | ||
this.windowCommunicator | ||
.setupHandshakeWithWindowParams(windowOpenParams, cbs, endSignals, popupType, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
} | ||
else { | ||
this.windowCommunicator | ||
.setupHandshakeWithPath(path, cbs, endSignals, popupType, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
} | ||
}); | ||
@@ -693,3 +855,3 @@ } | ||
} | ||
async signIn(input) { | ||
async signIn(input, windowOpenParams) { | ||
const publicKeyAddress = input?.address || this.publicKeyString; | ||
@@ -709,3 +871,3 @@ if (!publicKeyAddress) { | ||
const signInMessage = createSignInMessage(siwsRequiredFields); | ||
const signature = await this._signMessage(signInMessage, "sign_in_with_solana"); | ||
const signature = await this._signMessage(signInMessage, "sign_in_with_solana", windowOpenParams); | ||
return { | ||
@@ -712,0 +874,0 @@ account: { |
@@ -69,6 +69,7 @@ import { BaseSignInMessageSignerWalletAdapter, WalletConfigError, WalletConnectionError, WalletDisconnectionError, WalletError, WalletNotConnectedError, WalletNotReadyError, WalletPublicKeyError, WalletReadyState, WalletSendTransactionError, WalletSignInError, WalletSignMessageError, WalletSignTransactionError, } from "@solana/wallet-adapter-base"; | ||
} | ||
async _connect(onPublicKeyConnected, autoConnect = false) { | ||
async _connect({ forceNoDirectConnect, siwsInput, autoConnect = false, }) { | ||
console.log("BEGIN: connecting status for iden", this.connecting, this._iden); | ||
if (this.connected || this.connecting) | ||
return; | ||
let solanaSignInOutput; | ||
this._disconnected = false; | ||
@@ -100,4 +101,10 @@ try { | ||
try { | ||
publicKey = new PublicKey(await wallet.init(autoConnect ? false : this._directConnect, autoConnect)); | ||
console.log("DONE WALLET INIT!! connecting status right now is", this._connecting); | ||
const { pk, siwsOutput } = await wallet.init({ | ||
directConnect: forceNoDirectConnect ? false : this._directConnect, | ||
autoConnect, | ||
siwsInput, | ||
}); | ||
publicKey = new PublicKey(pk); | ||
solanaSignInOutput = siwsOutput; | ||
console.log("DONE WALLET INIT!! connecting status right now is", this._connecting, "disconnected", this._disconnected, "public key", pk, "siws output", siwsOutput); | ||
} | ||
@@ -114,5 +121,3 @@ catch (error) { | ||
this._publicKey = publicKey; | ||
if (onPublicKeyConnected) { | ||
onPublicKeyConnected(publicKey); | ||
} | ||
this.emit("connect", publicKey); | ||
console.log("FINISHED connecting"); | ||
@@ -130,12 +135,15 @@ // console.log("adapter.connect, connected"); | ||
} | ||
return { | ||
siwsOutput: solanaSignInOutput, | ||
}; | ||
} | ||
async autoConnect() { | ||
return this._connect((publicKey) => { | ||
this.emit("connect", publicKey); | ||
}, true); | ||
this._connect({ | ||
forceNoDirectConnect: true, | ||
}); | ||
return; | ||
} | ||
async connect() { | ||
return this._connect((publicKey) => { | ||
this.emit("connect", publicKey); | ||
}); | ||
this._connect({}); | ||
return; | ||
} | ||
@@ -145,2 +153,3 @@ async disconnect() { | ||
this._connecting = false; | ||
console.log("triggered disconnected!"); | ||
this._disconnected = true; | ||
@@ -241,7 +250,15 @@ if (wallet) { | ||
async signIn(input) { | ||
console.log("triggering sign in!"); | ||
try { | ||
let wasConnected = true; | ||
if (!this.connected) { | ||
wasConnected = false; | ||
await this._connect(); | ||
const output = await this._connect({ | ||
siwsInput: input, | ||
}); | ||
const siwsOutput = output?.siwsOutput; | ||
if (input) { | ||
if (!siwsOutput) { | ||
throw new Error("No Solana Sign In Output"); | ||
} | ||
return siwsOutput; | ||
} | ||
} | ||
@@ -256,5 +273,2 @@ const wallet = this._wallet; | ||
const siwsOutput = await wallet.signIn(input); | ||
if (!wasConnected) { | ||
this.emit("connect", publicKey); | ||
} | ||
return siwsOutput; | ||
@@ -261,0 +275,0 @@ } |
@@ -8,3 +8,3 @@ export const getTipLinkUrl = (buildEnv) => { | ||
case "development": | ||
return "https://dev.tiplink.io"; | ||
return "https://alex-devel.tiplink.io"; | ||
case "adapter": | ||
@@ -11,0 +11,0 @@ return "https://adapter.tiplink.io"; |
@@ -42,3 +42,7 @@ import { getTipLinkUrl } from "./utils.js"; | ||
} | ||
const { type, cb: callback } = windowCallbacks[event.data.type]; | ||
const windowCallback = windowCallbacks[event.data.type]; | ||
if (!windowCallback) { | ||
return; | ||
} | ||
const { type, cb: callback } = windowCallback; | ||
if (endSignalsSet.has(event.data.type)) { | ||
@@ -105,4 +109,3 @@ endFn?.(); | ||
checkPopupClosed = setInterval(function () { | ||
console.log("STILL CHECKING 2"); | ||
if (popup.closed) { | ||
if (!popup || popup.closed) { | ||
clearInterval(checkPopupClosed); | ||
@@ -123,3 +126,2 @@ upperReject("User closed popup"); | ||
checkPopupClosed = setInterval(function () { | ||
console.log("STILL CHECKING 1"); | ||
if (popup.closed) { | ||
@@ -126,0 +128,0 @@ clearInterval(checkPopupClosed); |
@@ -40,2 +40,5 @@ /// <reference types="node" /> | ||
private getCloseButtonUrl; | ||
private getTipLinkLogoUrl; | ||
private getGoogleLogoUrl; | ||
private getBackgroundImageUrl; | ||
private popupTypeMessage; | ||
@@ -46,6 +49,14 @@ private fadeIn; | ||
private showTipLinkAutoconnectToast; | ||
private _createDirectLoginModal; | ||
private _createPopupBlockAlert; | ||
private getQueryParams; | ||
postReady(windowParams: WindowOpenParams): Promise<NodeJS.Timeout>; | ||
init(directConnect: boolean, autoConnect: boolean): Promise<string>; | ||
postReady(windowParams: WindowOpenParams, checkAllowlist?: boolean): Promise<NodeJS.Timeout | undefined>; | ||
init({ directConnect, autoConnect, siwsInput, }: { | ||
directConnect: boolean; | ||
autoConnect?: boolean; | ||
siwsInput?: SolanaSignInInput; | ||
}): Promise<{ | ||
pk: string; | ||
siwsOutput?: SolanaSignInOutput; | ||
}>; | ||
disconnect(): Promise<void>; | ||
@@ -68,4 +79,4 @@ cleanUp(): Promise<void>; | ||
}>; | ||
signIn(input?: SolanaSignInInput): Promise<SolanaSignInOutput>; | ||
signIn(input?: SolanaSignInInput, windowOpenParams?: WindowOpenParams): Promise<SolanaSignInOutput>; | ||
} | ||
//# sourceMappingURL=embed.d.ts.map |
{ | ||
"name": "@tiplink/wallet-adapter", | ||
"version": "0.1.7", | ||
"version": "0.1.8", | ||
"author": "Alex Fung", | ||
@@ -5,0 +5,0 @@ "contributors": [ |
414
src/embed.ts
@@ -14,3 +14,3 @@ /* | ||
import { getTipLinkUrl } from "./utils.js"; | ||
import type { WindowOpenParams } from "./window.js"; | ||
import type { WindowCallbacks, WindowOpenParams } from "./window.js"; | ||
import { CallbackType, WindowCommunicator } from "./window.js"; | ||
@@ -177,2 +177,26 @@ import { | ||
private getTipLinkLogoUrl(): string { | ||
const logoUrl = new URL( | ||
"adapter-tiplink-logo.svg", | ||
getTipLinkUrl(this.buildEnv) | ||
); | ||
return logoUrl.toString(); | ||
} | ||
private getGoogleLogoUrl(): string { | ||
const logoUrl = new URL( | ||
"adapter-google-logo.svg", | ||
getTipLinkUrl(this.buildEnv) | ||
); | ||
return logoUrl.toString(); | ||
} | ||
private getBackgroundImageUrl(): string { | ||
const logoUrl = new URL( | ||
"adapter-modal-background.png", | ||
getTipLinkUrl(this.buildEnv) | ||
); | ||
return logoUrl.toString(); | ||
} | ||
private popupTypeMessage = (popupType: PopupType) => { | ||
@@ -274,2 +298,90 @@ const baseUrl = getTipLinkUrl(this.buildEnv); | ||
private async _createDirectLoginModal( | ||
onClick: () => void, | ||
onClose: () => void | ||
): Promise<void> { | ||
const modal = htmlToElement<HTMLDivElement>( | ||
"<div id='tipLinkAlertModal'></div>" | ||
); | ||
const innerContainer = htmlToElement<HTMLDivElement>( | ||
`<div id='tipLinkAlert__inner_container' style="background-image: url(${this.getBackgroundImageUrl()}); background-color: #F2F8FC; background-repeat: no-repeat; background-position: center; background-size: cover"></div>` | ||
); | ||
const overlay = htmlToElement<HTMLDivElement>( | ||
"<div id='tipLinkAlert__modal_overlay'></div>" | ||
); | ||
const tipLinkAlert = htmlToElement<HTMLDivElement>( | ||
'<div id="tipLinkAlert" class="tipLink-alert--v2"></div>' | ||
); | ||
const tipLinkLoginContainer = htmlToElement<HTMLDivElement>( | ||
`<div id="tipLinkAlert__login_container">` + | ||
`<img src="${this.getTipLinkLogoUrl()}" id="tipLinkAlert__login_tiplink_logo"/>` + | ||
`<div id="tipLinkAlert__login_title">${"TipLink: the world's simplest wallet"}</div>` + | ||
`<div id="tipLinkAlert__login_desc1">${"Login/create your TipLink wallet with just 2 clicks."}</div>` + | ||
`<div id="tipLinkAlert__login_desc2">${"You'll be asked to sign in securely with Solana after logging in."}</div>` + | ||
"</div>" | ||
); | ||
const tipLinkLoginButton = htmlToElement<HTMLDivElement>( | ||
`<div id="tipLinkAlert__login_btn">` + | ||
`<div id="tipLinkAlert__google_logo_container"><img src="${this.getGoogleLogoUrl()}" id="tipLinkAlert__google_logo"/></div>` + | ||
`<p id="tipLinkAlert_continue_with_google">${"Continue with Google"}</p>` + | ||
`</div>` | ||
); | ||
const closeButtonIconUrl = this.getCloseButtonUrl(); | ||
const closeButton = htmlToElement( | ||
`<div id="tipLinkAlert__close-btn"><img id="tipLinkAlert__close-btn-image" src="${closeButtonIconUrl}"/></div>` | ||
); | ||
tipLinkLoginContainer.appendChild(tipLinkLoginButton); | ||
tipLinkAlert.appendChild(tipLinkLoginContainer); | ||
innerContainer.appendChild(tipLinkAlert); | ||
innerContainer.appendChild(closeButton); | ||
modal.appendChild(innerContainer); | ||
modal.appendChild(overlay); | ||
const removePopupBlockedAlert = () => { | ||
modal.remove(); | ||
if ( | ||
this.tipLinkAlertContainer && | ||
this.tipLinkAlertContainer.children.length === 0 | ||
) { | ||
this.tipLinkAlertContainer.style.display = "none"; | ||
} | ||
}; | ||
const bindOnLoad = () => { | ||
tipLinkLoginButton.addEventListener("click", () => { | ||
onClick(); | ||
removePopupBlockedAlert(); | ||
}); | ||
}; | ||
const bindCloseButton = () => { | ||
closeButton.addEventListener("click", () => { | ||
removePopupBlockedAlert(); | ||
onClose(); | ||
}); | ||
overlay.addEventListener("mousedown", () => { | ||
removePopupBlockedAlert(); | ||
onClose(); | ||
}); | ||
}; | ||
const attachOnLoad = () => { | ||
if (this.tipLinkAlertContainer) { | ||
this.tipLinkAlertContainer.appendChild(modal); | ||
} | ||
}; | ||
attachOnLoad(); | ||
bindCloseButton(); | ||
bindOnLoad(); | ||
if (this.tipLinkAlertContainer) { | ||
this.tipLinkAlertContainer.style.display = "block"; | ||
} | ||
} | ||
private async _createPopupBlockAlert( | ||
@@ -388,3 +500,6 @@ onClick: () => void, | ||
async postReady(windowParams: WindowOpenParams): Promise<NodeJS.Timeout> { | ||
async postReady( | ||
windowParams: WindowOpenParams, | ||
checkAllowlist = true | ||
): Promise<NodeJS.Timeout | undefined> { | ||
let interval: NodeJS.Timeout | undefined = undefined; | ||
@@ -400,13 +515,17 @@ return new Promise((resolve, reject) => { | ||
clearInterval(interval); | ||
const timeout = setTimeout(() => { | ||
this._createPopupBlockAlert( | ||
() => undefined, | ||
() => undefined, | ||
PopupType.NOT_ALLOWLISTED | ||
); | ||
console.error( | ||
"This application has not been allowlisted for the TipLink Wallet Adapter. Please reach out to contact@tiplink.io for support." | ||
); | ||
}, NOT_ALLOWLISTED_TIMEOUT_MS); | ||
resolve(timeout); | ||
if (checkAllowlist) { | ||
const timeout = setTimeout(() => { | ||
this._createPopupBlockAlert( | ||
() => undefined, | ||
() => undefined, | ||
PopupType.NOT_ALLOWLISTED | ||
); | ||
console.error( | ||
"This application has not been allowlisted for the TipLink Wallet Adapter. Please reach out to contact@tiplink.io for support." | ||
); | ||
}, NOT_ALLOWLISTED_TIMEOUT_MS); | ||
resolve(timeout); | ||
} else { | ||
resolve(undefined); | ||
} | ||
}, | ||
@@ -435,10 +554,28 @@ }, | ||
async init(directConnect: boolean, autoConnect: boolean): Promise<string> { | ||
async init({ | ||
directConnect, | ||
autoConnect, | ||
siwsInput, | ||
}: { | ||
directConnect: boolean; | ||
autoConnect?: boolean; | ||
siwsInput?: SolanaSignInInput; | ||
}): Promise<{ | ||
pk: string; | ||
siwsOutput?: SolanaSignInOutput; | ||
}> { | ||
let windowParams: WindowOpenParams | undefined = undefined; | ||
let siwsLoginPopupBlocked = false; | ||
if (directConnect) { | ||
windowParams = this.windowCommunicator.openPopup( | ||
"/adapter_login?forceLogin=true&isDirect=true" | ||
`/adapter_login?forceLogin=true&isDirect=true${ | ||
siwsInput ? "&isSiws=true" : "" | ||
}` | ||
); | ||
if (!windowParams.popup || windowParams.popup.closed) { | ||
directConnect = false; | ||
if (!siwsInput) { | ||
directConnect = false; | ||
} else { | ||
siwsLoginPopupBlocked = true; | ||
} | ||
} | ||
@@ -474,12 +611,15 @@ } | ||
const ogListener = (event: any) => { | ||
const { data } = event; | ||
console.log("received message", data); | ||
if (data.type === "loaded") { | ||
const { publicKey } = data; | ||
this.publicKeyString = publicKey; | ||
this.hideIframe(); | ||
} | ||
}; | ||
window.addEventListener("message", ogListener); | ||
let ogListener: ((event: any) => void) | undefined = undefined; | ||
if (!directConnect) { | ||
ogListener = (event: any) => { | ||
const { data } = event; | ||
console.log("received message", data); | ||
if (data.type === "loaded") { | ||
const { publicKey } = data; | ||
this.publicKeyString = publicKey; | ||
this.hideIframe(); | ||
} | ||
}; | ||
window.addEventListener("message", ogListener); | ||
} | ||
@@ -497,5 +637,12 @@ this.tipLinkAlertContainer = htmlToElement<HTMLDivElement>( | ||
const handleSetup = async (): Promise<string> => { | ||
return new Promise<string>((resolve, reject) => { | ||
const handleSetup = async (): Promise<{ | ||
pk: string; | ||
siwsOutput?: SolanaSignInOutput; | ||
}> => { | ||
return new Promise<{ | ||
pk: string; | ||
siwsOutput?: SolanaSignInOutput; | ||
}>((resolve, reject) => { | ||
console.log("actually RUNNING handle setup"); | ||
const fnsAtEnd: (() => void)[] = []; | ||
try { | ||
@@ -534,2 +681,3 @@ if (this.tipLinkIframe === undefined) { | ||
const interval: NodeJS.Timeout | undefined = undefined; | ||
const { close: closeIframeChannel } = | ||
@@ -558,3 +706,39 @@ this.windowCommunicator.setupHandshakeWithIframe( | ||
} | ||
resolve(publicKey); | ||
console.log("triggered loaded!"); | ||
let siwsOutput: SolanaSignInOutput | undefined = | ||
undefined; | ||
if (siwsInput && windowParams) { | ||
console.log( | ||
"setting up signin", | ||
siwsInput, | ||
windowParams | ||
); | ||
try { | ||
console.log("CALLING sign in from callback"); | ||
siwsOutput = await this.signIn( | ||
siwsInput, | ||
windowParams | ||
); | ||
} catch (err) { | ||
reject(err); | ||
} | ||
} else if (!windowParams) { | ||
console.error("windowParams is empty!"); | ||
} | ||
console.log( | ||
"publicKey", | ||
publicKey, | ||
"siwsOutput", | ||
siwsOutput | ||
); | ||
clearInterval(interval); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
resolve({ | ||
pk: publicKey, | ||
siwsOutput, | ||
}); | ||
}, | ||
@@ -573,2 +757,7 @@ }, | ||
this.cleanUp(); | ||
clearInterval(interval); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via cLOSED"); | ||
reject(); | ||
@@ -580,5 +769,7 @@ }, | ||
); | ||
fnsAtEnd.push(closeIframeChannel); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
window.removeEventListener("message", ogListener); | ||
if (directConnect) { | ||
@@ -608,4 +799,25 @@ if (windowParams?.popup && !windowParams?.popup.closed) { | ||
}); | ||
} else if (siwsLoginPopupBlocked) { | ||
// show popup dialog, | ||
// if user clicks to not open dialog, make sure to reject | ||
this._createDirectLoginModal( | ||
() => { | ||
windowParams = this.windowCommunicator.openPopup( | ||
`/adapter_login?forceLogin=true&isDirect=true${ | ||
siwsInput ? "&isSiws=true" : "" | ||
}` | ||
); | ||
this.postReady(windowParams, false); | ||
}, | ||
() => { | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via dialog closed"); | ||
closeIframeChannel(); | ||
reject(); | ||
} | ||
); | ||
} else { | ||
reject(new Error("window is closed")); | ||
reject(new Error("window is closed early")); | ||
} | ||
@@ -615,2 +827,4 @@ } | ||
if (this.publicKeyString) { | ||
// if the og listener above triggered we would have detected the public key | ||
// saved from the iframe from a previous session | ||
this.hideIframe(); | ||
@@ -622,3 +836,9 @@ closeIframeChannel(); | ||
} | ||
resolve(this.publicKeyString); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("resolved saved public key from iframe"); | ||
resolve({ | ||
pk: this.publicKeyString, | ||
}); | ||
} | ||
@@ -628,3 +848,9 @@ }); | ||
console.log("REJECTING error", error); | ||
if (ogListener) { | ||
window.removeEventListener("message", ogListener); | ||
} | ||
console.log("rejected via errior"); | ||
reject(error); | ||
} finally { | ||
fnsAtEnd.forEach((fn) => fn()); | ||
} | ||
@@ -866,56 +1092,70 @@ }); | ||
message: Uint8Array, | ||
path: string | ||
path: string, | ||
windowOpenParams?: WindowOpenParams | ||
): Promise<Uint8Array> { | ||
return new Promise<Uint8Array>((resolve, reject) => { | ||
this.extendSession(); | ||
void this.windowCommunicator | ||
.setupHandshakeWithPath( | ||
path, | ||
{ | ||
loaded: { | ||
type: CallbackType.POST, | ||
cb: async () => { | ||
return { | ||
message: Buffer.from(message).toString("base64"), | ||
}; | ||
}, | ||
}, | ||
signed_message: { | ||
type: CallbackType.DEFAULT, | ||
cb: async (data: any) => { | ||
const signedMessage = Buffer.from( | ||
data.signed_message, | ||
"base64" | ||
); | ||
resolve(signedMessage); | ||
}, | ||
}, | ||
closed: { | ||
type: CallbackType.DEFAULT, | ||
cb: async () => { | ||
reject("User rejected message"); | ||
}, | ||
}, | ||
error: { | ||
type: CallbackType.DEFAULT, | ||
cb: async (data: any) => { | ||
reject(data.message); | ||
}, | ||
}, | ||
accountChanged: { | ||
type: CallbackType.DEFAULT, | ||
cb: async (data: any) => { | ||
console.log("received account changed!"); | ||
await this.updatePublicKey(data.publicKey); | ||
reject("User changed account"); | ||
}, | ||
}, | ||
const cbs: WindowCallbacks = { | ||
loaded: { | ||
type: CallbackType.POST, | ||
cb: async () => { | ||
console.log( | ||
"triggered loaded on sign message, posting message", | ||
message | ||
); | ||
return { | ||
message: Buffer.from(message).toString("base64"), | ||
}; | ||
}, | ||
["signed_message", "closed", "accountChanged"], | ||
PopupType.MESSAGE, | ||
reject | ||
) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
}, | ||
signed_message: { | ||
type: CallbackType.DEFAULT, | ||
cb: async (data: any) => { | ||
const signedMessage = Buffer.from(data.signed_message, "base64"); | ||
resolve(signedMessage); | ||
}, | ||
}, | ||
closed: { | ||
type: CallbackType.DEFAULT, | ||
cb: async () => { | ||
reject("User rejected message"); | ||
}, | ||
}, | ||
error: { | ||
type: CallbackType.DEFAULT, | ||
cb: async (data: any) => { | ||
reject(data.message); | ||
}, | ||
}, | ||
accountChanged: { | ||
type: CallbackType.DEFAULT, | ||
cb: async (data: any) => { | ||
console.log("received account changed!"); | ||
await this.updatePublicKey(data.publicKey); | ||
reject("User changed account"); | ||
}, | ||
}, | ||
}; | ||
const endSignals = ["signed_message", "closed", "accountChanged"]; | ||
const popupType = PopupType.MESSAGE; | ||
if (windowOpenParams) { | ||
console.log("window open params setting up handshake"); | ||
this.windowCommunicator | ||
.setupHandshakeWithWindowParams( | ||
windowOpenParams, | ||
cbs, | ||
endSignals, | ||
popupType, | ||
reject | ||
) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
} else { | ||
this.windowCommunicator | ||
.setupHandshakeWithPath(path, cbs, endSignals, popupType, reject) | ||
.catch((error) => { | ||
reject(error); | ||
}); | ||
} | ||
}); | ||
@@ -928,3 +1168,6 @@ } | ||
async signIn(input?: SolanaSignInInput): Promise<SolanaSignInOutput> { | ||
async signIn( | ||
input?: SolanaSignInInput, | ||
windowOpenParams?: WindowOpenParams | ||
): Promise<SolanaSignInOutput> { | ||
const publicKeyAddress = input?.address || this.publicKeyString; | ||
@@ -946,3 +1189,4 @@ if (!publicKeyAddress) { | ||
signInMessage, | ||
"sign_in_with_solana" | ||
"sign_in_with_solana", | ||
windowOpenParams | ||
); | ||
@@ -949,0 +1193,0 @@ return { |
@@ -37,2 +37,3 @@ import type { | ||
} from "@solana/wallet-standard-features"; | ||
import type { WindowOpenParams } from "./window.js"; | ||
@@ -51,2 +52,5 @@ export type { TIPLINK_BUILD_ENV_TYPE }; | ||
type ConnectOutput = { | ||
siwsOutput?: SolanaSignInOutput; | ||
}; | ||
export class TipLinkWalletAdapter extends BaseSignInMessageSignerWalletAdapter { | ||
@@ -141,6 +145,11 @@ name = GoogleViaTipLinkWalletName; | ||
private async _connect( | ||
onPublicKeyConnected?: (publicKey: PublicKey) => void, | ||
autoConnect = false | ||
): Promise<void> { | ||
private async _connect({ | ||
forceNoDirectConnect, | ||
siwsInput, | ||
autoConnect = false, | ||
}: { | ||
forceNoDirectConnect?: boolean; | ||
siwsInput?: SolanaSignInInput; | ||
autoConnect?: boolean; | ||
}): Promise<ConnectOutput | undefined> { | ||
console.log( | ||
@@ -152,2 +161,4 @@ "BEGIN: connecting status for iden", | ||
if (this.connected || this.connecting) return; | ||
let solanaSignInOutput: SolanaSignInOutput | undefined; | ||
this._disconnected = false; | ||
@@ -182,11 +193,18 @@ try { | ||
try { | ||
publicKey = new PublicKey( | ||
await wallet.init( | ||
autoConnect ? false : this._directConnect, | ||
autoConnect | ||
) | ||
); | ||
const { pk, siwsOutput } = await wallet.init({ | ||
directConnect: forceNoDirectConnect ? false : this._directConnect, | ||
autoConnect, | ||
siwsInput, | ||
}); | ||
publicKey = new PublicKey(pk); | ||
solanaSignInOutput = siwsOutput; | ||
console.log( | ||
"DONE WALLET INIT!! connecting status right now is", | ||
this._connecting | ||
this._connecting, | ||
"disconnected", | ||
this._disconnected, | ||
"public key", | ||
pk, | ||
"siws output", | ||
siwsOutput | ||
); | ||
@@ -208,5 +226,3 @@ } catch (error: any) { | ||
if (onPublicKeyConnected) { | ||
onPublicKeyConnected(publicKey); | ||
} | ||
this.emit("connect", publicKey); | ||
console.log("FINISHED connecting"); | ||
@@ -222,14 +238,17 @@ // console.log("adapter.connect, connected"); | ||
} | ||
return { | ||
siwsOutput: solanaSignInOutput, | ||
}; | ||
} | ||
async autoConnect(): Promise<void> { | ||
return this._connect((publicKey: PublicKey) => { | ||
this.emit("connect", publicKey); | ||
}, true); | ||
this._connect({ | ||
forceNoDirectConnect: true, | ||
}); | ||
return; | ||
} | ||
async connect(): Promise<void> { | ||
return this._connect((publicKey: PublicKey) => { | ||
this.emit("connect", publicKey); | ||
}); | ||
this._connect({}); | ||
return; | ||
} | ||
@@ -240,2 +259,3 @@ | ||
this._connecting = false; | ||
console.log("triggered disconnected!"); | ||
this._disconnected = true; | ||
@@ -349,7 +369,15 @@ if (wallet) { | ||
async signIn(input?: SolanaSignInInput): Promise<SolanaSignInOutput> { | ||
console.log("triggering sign in!"); | ||
try { | ||
let wasConnected = true; | ||
if (!this.connected) { | ||
wasConnected = false; | ||
await this._connect(); | ||
const output = await this._connect({ | ||
siwsInput: input, | ||
}); | ||
const siwsOutput = output?.siwsOutput; | ||
if (input) { | ||
if (!siwsOutput) { | ||
throw new Error("No Solana Sign In Output"); | ||
} | ||
return siwsOutput; | ||
} | ||
} | ||
@@ -366,6 +394,2 @@ | ||
if (!wasConnected) { | ||
this.emit("connect", publicKey); | ||
} | ||
return siwsOutput; | ||
@@ -372,0 +396,0 @@ } catch (error: any) { |
@@ -96,3 +96,7 @@ import type { PopupType } from "./embed.js"; | ||
} | ||
const { type, cb: callback } = windowCallbacks[event.data.type]; | ||
const windowCallback = windowCallbacks[event.data.type]; | ||
if (!windowCallback) { | ||
return; | ||
} | ||
const { type, cb: callback } = windowCallback; | ||
if (endSignalsSet.has(event.data.type)) { | ||
@@ -195,4 +199,3 @@ endFn?.(); | ||
checkPopupClosed = setInterval(function () { | ||
console.log("STILL CHECKING 2"); | ||
if (popup.closed) { | ||
if (!popup || popup.closed) { | ||
clearInterval(checkPopupClosed); | ||
@@ -222,3 +225,2 @@ upperReject("User closed popup"); | ||
checkPopupClosed = setInterval(function () { | ||
console.log("STILL CHECKING 1"); | ||
if (popup.closed) { | ||
@@ -225,0 +227,0 @@ clearInterval(checkPopupClosed); |
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
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
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
321335
4951