Как редактировать метаданные на фантомном кошельке, когда он предлагает подключиться из моего приложения SwiftuiHtml

Программисты Html
Ответить
Anonymous
 Как редактировать метаданные на фантомном кошельке, когда он предлагает подключиться из моего приложения Swiftui

Сообщение Anonymous »

В настоящее время мой код работает для подключения к Phantom Wallet, но я не уверен, как редактировать, как Phantom Wallet отображает информацию о моем приложении (фото и имя). Я попытался размещать сайт netlify index.html с метаданными для него, который тоже не сработал.

Код: Выделить всё

import SwiftUI
import CryptoKit

struct Base58 {
private static let alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
private static let base = UInt32(alphabet.count)

static func encode(_ data: Data) -> String {
var x = data
var answer = ""

var leadingZeros = 0
for byte in x {
if byte == 0 { leadingZeros += 1 }
else { break }
}

var digits = [UInt8]()
while !x.isEmpty {
var remainder: UInt32 = 0
var temp = Data()
for byte in x {
let value = UInt32(byte) + remainder * 256
let digit = value / base
remainder = value % base
if temp.isEmpty && digit == 0 { continue }
temp.append(UInt8(digit))
}
digits.append(UInt8(remainder))
x = temp
}

answer = String(repeating: "1", count: leadingZeros)
for digit in digits.reversed() {
answer.append(alphabet[alphabet.index(alphabet.startIndex, offsetBy: Int(digit))])
}
return answer
}

static func decode(_ string: String) -> Data? {
var answer = Data()

for char in string {
guard let charIndex = alphabet.firstIndex(of: char)?.utf16Offset(in: alphabet) else {
return nil
}
var carry = UInt32(charIndex)
var temp = Data()
for byte in answer.reversed() {
let value = UInt32(byte) * base + carry
carry = value / 256
temp.insert(UInt8(value % 256), at: 0)
}
while carry > 0 {
temp.insert(UInt8(carry % 256), at: 0)
carry /= 256
}
answer = temp
}

var leadingOnes = 0
for char in string {
if char == "1"  { leadingOnes += 1 }
else { break }
}

let leadingZeros = Data(repeating: 0, count: leadingOnes)
return leadingZeros + answer
}
}

struct PhantomWalletView: View {
@State private var isConnected = false
@State private var publicKey: String = ""
@State private var session: String = ""
@State private var dappKeyPair: Curve25519.KeyAgreement.PrivateKey?
@State private var sharedSecret: SymmetricKey?

var body: some View {
VStack(spacing: 20) {
Text("Phantom Wallet Integration")
.font(.title)

if isConnected {
VStack(spacing: 15) {
Text("Connected!")
.foregroundColor(.green)
.font(.headline)
Text("Public Key: \(publicKey)")
.font(.caption)
.multilineTextAlignment(.center)
.padding(.horizontal)

Button("Sign Message") {
signMessage()
}
.buttonStyle(.borderedProminent)

Button("Disconnect") {
disconnect()
}
.buttonStyle(.bordered)
}
} else {
Button("Connect to Phantom") {
connectToPhantom()
}
.buttonStyle(.borderedProminent)
}
}
.padding()
.onOpenURL { url in
handlePhantomResponse(url: url)
}
}

// MARK: - Phantom Integration Methods

func connectToPhantom() {
dappKeyPair = Curve25519.KeyAgreement.PrivateKey()

let appURL = "https://coinclip.netlify.app"
let redirectLink = "coinclip://phantom-response"
let dappPublicKey = dappKeyPair!.publicKey.rawRepresentation

var components = URLComponents(string: "https://phantom.app/ul/v1/connect")!
components.queryItems = [
URLQueryItem(name: "app_url", value: appURL),
URLQueryItem(name: "dapp_encryption_public_key", value: Base58.encode(dappPublicKey)),
URLQueryItem(name: "redirect_link", value: redirectLink),
URLQueryItem(name: "cluster", value: "mainnet-beta")
]

if let url = components.url {
UIApplication.shared.open(url)
}
}

func signMessage() {
guard let dappKeyPair = dappKeyPair,
let sharedSecret = sharedSecret,
!session.isEmpty else {
print("Cannot sign message: missing keypair, shared secret, or session.")
return
}

let message = "Hello from your SwiftUI dApp!"
let payloadDict: [String: Any] = ["message": message, "session": session, "display": "utf8"]

guard let payloadData = try? JSONSerialization.data(withJSONObject: payloadDict),
let (encryptedPayloadData, nonceData) = encryptData(payloadData, with: sharedSecret) else {
return
}

let redirectLink = "coinclip://phantom-response"

var components = URLComponents(string: "https://phantom.app/ul/v1/signMessage")!
components.queryItems = [
URLQueryItem(name: "dapp_encryption_public_key", value: Base58.encode(dappKeyPair.publicKey.rawRepresentation)),
URLQueryItem(name: "nonce", value: Base58.encode(nonceData)),
URLQueryItem(name: "redirect_link", value: redirectLink),
URLQueryItem(name: "payload", value: Base58.encode(encryptedPayloadData))
]

if let url = components.url {
UIApplication.shared.open(url)
}
}

func disconnect() {

isConnected = false
publicKey = ""
session = ""
dappKeyPair = nil
sharedSecret = nil
}

func handlePhantomResponse(url:  URL) {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems else { return }

let params = queryItems.reduce(into: [String: String]()) { $0[$1.name] = $1.value }

if let errorCode = params["errorCode"] {
print("Phantom error: \(errorCode) - \(params["errorMessage"] ?? "Unknown error")")
return
}

// Handle connect response
if let phantomPublicKeyString = params["phantom_encryption_public_key"],
let nonceString = params["nonce"],
let dataString = params["data"] {

guard let dappKeyPair = self.dappKeyPair,
let phantomPublicKeyData = Base58.decode(phantomPublicKeyString),
let nonceData = Base58.decode(nonceString),
let encryptedData = Base58.decode(dataString) else {
print("Failed to decode response or missing dApp keypair.")
return
}

do {
let phantomPublicKey = try Curve25519.KeyAgreement.PublicKey(rawRepresentation: phantomPublicKeyData)
let secret = try dappKeyPair.sharedSecretFromKeyAgreement(with: phantomPublicKey)

let symmetricKey = secret.hkdfDerivedSymmetricKey(
using: SHA256.self, salt: Data(), sharedInfo: Data(), outputByteCount: 32
)
self.sharedSecret = symmetricKey

if let decryptedData = decryptData(encryptedData: encryptedData, nonceData: nonceData, with: symmetricKey),
let json = try JSONSerialization.jsonObject(with: decryptedData) as? [String: Any] {
self.publicKey = json["public_key"] as? String ?? ""
self.session = json["session"] as? String ?? ""
self.isConnected = true
print("Successfully connected to Phantom!")
}
} catch {
print("Error handling connect response: \(error)")
}
}

// Handle sign message response
if let signatureString = params["signature"] {
if let signatureData = Base58.decode(signatureString) {
print("Message signed successfully! Signature: \(signatureData.map { String(format: "%02hhx", $0) }.joined())")
}
}
}

// MARK: - Crypto Helper Methods

func encryptData(_ data: Data, with key: SymmetricKey) -> (payload: Data, nonce: Data)? {
do {
let sealedBox = try ChaChaPoly.seal(data, using: key)
let nonceData = sealedBox.nonce.withUnsafeBytes { Data($0) }

let payload = sealedBox.ciphertext + sealedBox.tag
return (payload: payload, nonce: nonceData)
} catch {
print("Error: Encryption failed - \(error)")
return nil
}
}

func decryptData(encryptedData: Data, nonceData: Data, with key: SymmetricKey) -> Data? {

guard encryptedData.count > 16 else {
print("Error: Encrypted data is too short to contain a tag.")
return nil
}

let tagIndex = encryptedData.count - 16
let ciphertext = encryptedData.prefix(upTo: tagIndex)
let tag = encryptedData.suffix(from: tagIndex)

do {
let nonce = try ChaChaPoly.Nonce(data: nonceData)
// Reconstruct the SealedBox with the separated nonce, ciphertext, and tag.
let sealedBox = try ChaChaPoly.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag)
return try ChaChaPoly.open(sealedBox, using: key)
} catch {
print("Error: Decryption failed - \(error)")
return nil
}
}
}

// MARK: - Extensions

extension Data {
/// Encodes data into a Base58 string.
func base58EncodedString() ->  String {
return Base58.encode(self)
}
}
< /code>
my index.html code: < /p>









CoinClip













Coinclip App Metadata
This page provides the necessary metadata for Phantom Wallet integration.


Как он выглядит в Phantom Wallet:


Подробнее здесь: https://stackoverflow.com/questions/796 ... from-my-sw
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Html»