Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.13.0 #1306

Closed
wants to merge 14 commits into from
4 changes: 4 additions & 0 deletions .env.DApp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SCHEME = "DApp"
APP_IDENTIFIER = "com.walletconnect.dapp"
MATCH_IDENTIFIERS = "com.walletconnect.dapp"
APPLE_ID = "1606875879"
10 changes: 9 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ name: release

on:
workflow_dispatch:
inputs:
app:
type: choice
description: Which sample app to release
options:
- DApp
- WalletApp
- Showcase

jobs:
build:
Expand Down Expand Up @@ -32,4 +40,4 @@ jobs:
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
WALLETAPP_SENTRY_DSN: ${{ secrets.WALLETAPP_SENTRY_DSN }}
run: |
make release_wallet APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) PROJECT_ID=${{ secrets.RELEASE_PROJECT_ID }} WALLETAPP_SENTRY_DSN=${{ secrets.WALLETAPP_SENTRY_DSN }} MIXPANEL_TOKEN=${{secrets.MIXPANEL_TOKEN}}
make release APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) PROJECT_ID=${{ secrets.RELEASE_PROJECT_ID }} WALLETAPP_SENTRY_DSN=${{ secrets.WALLETAPP_SENTRY_DSN }} MIXPANEL_TOKEN=${{secrets.MIXPANEL_TOKEN}} APP=${{ github.event.inputs.app }}
46 changes: 23 additions & 23 deletions Example/IntegrationTests/Push/NotifyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,29 +245,29 @@ final class NotifyTests: XCTestCase {
}
}

func testFetchHistory() async throws {
let subscribeExpectation = expectation(description: "fetch notify subscription")
let account = Account("eip155:1:0x622b17376F76d72C43527a917f59273247A917b4")!

var subscription: NotifySubscription!
walletNotifyClientA.subscriptionsPublisher
.sink { subscriptions in
subscription = subscriptions.first
subscribeExpectation.fulfill()
}.store(in: &publishers)

try await walletNotifyClientA.register(account: account, domain: gmDappDomain) { message in
let privateKey = Data(hex: "c3ff8a0ae33ac5d58e515055c5870fa2f220d070997bd6fd77a5f2c148528ff0")
let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create(projectId: InputConfig.projectId)
return try! signer.sign(message: message, privateKey: privateKey, type: .eip191)
}

await fulfillment(of: [subscribeExpectation], timeout: InputConfig.defaultTimeout)

let hasMore = try await walletNotifyClientA.fetchHistory(subscription: subscription, after: nil, limit: 20)
XCTAssertTrue(hasMore)
XCTAssertTrue(walletNotifyClientA.getMessageHistory(topic: subscription.topic).count == 20)
}
// func testFetchHistory() async throws {
// let subscribeExpectation = expectation(description: "fetch notify subscription")
// let account = Account("eip155:1:0x622b17376F76d72C43527a917f59273247A917b4")!
//
// var subscription: NotifySubscription!
// walletNotifyClientA.subscriptionsPublisher
// .sink { subscriptions in
// subscription = subscriptions.first
// subscribeExpectation.fulfill()
// }.store(in: &publishers)
//
// try await walletNotifyClientA.register(account: account, domain: gmDappDomain) { message in
// let privateKey = Data(hex: "c3ff8a0ae33ac5d58e515055c5870fa2f220d070997bd6fd77a5f2c148528ff0")
// let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create(projectId: InputConfig.projectId)
// return try! signer.sign(message: message, privateKey: privateKey, type: .eip191)
// }
//
// await fulfillment(of: [subscribeExpectation], timeout: InputConfig.defaultTimeout)
//
// let hasMore = try await walletNotifyClientA.fetchHistory(subscription: subscription, after: nil, limit: 20)
// XCTAssertTrue(hasMore)
// XCTAssertTrue(walletNotifyClientA.getMessageHistory(topic: subscription.topic).count == 20)
// }
}


Expand Down
4 changes: 2 additions & 2 deletions Example/IntegrationTests/Sign/SignClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ final class SignClientTests: XCTestCase {
wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in
Task(priority: .high) {
do {
try await wallet.reject(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason
try await wallet.reject(proposalId: proposal.id, reason: .unsupportedChains)
store.rejectedProposal = proposal
semaphore.signal()
} catch { XCTFail("\(error)") }
Expand All @@ -119,7 +119,7 @@ final class SignClientTests: XCTestCase {
dapp.sessionRejectionPublisher.sink { proposal, _ in
semaphore.wait()
XCTAssertEqual(store.rejectedProposal, proposal)
sessionRejectExpectation.fulfill() // TODO: Assert reason code
sessionRejectExpectation.fulfill()
}.store(in: &publishers)
await fulfillment(of: [sessionRejectExpectation], timeout: InputConfig.defaultTimeout)
}
Expand Down
8 changes: 5 additions & 3 deletions Example/Shared/Signer/ETHSigner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ struct ETHSigner {
return AnyCodable(result)
}

func sendTransaction(_ params: AnyCodable) -> AnyCodable {
let params = try! params.get([EthereumTransaction].self)
func sendTransaction(_ params: AnyCodable) throws -> AnyCodable {
let params = try params.get([EthereumTransaction].self)
var transaction = params[0]
transaction.gas = EthereumQuantity(quantity: BigUInt("1234"))
transaction.nonce = EthereumQuantity(quantity: BigUInt("0"))
transaction.gasPrice = EthereumQuantity(quantity: BigUInt(0))
print(transaction.description)
let signedTx = try! transaction.sign(with: self.privateKey, chainId: 4)
let signedTx = try transaction.sign(with: self.privateKey, chainId: 4)
let (r, s, v) = (signedTx.r, signedTx.s, signedTx.v)
let result = r.hex() + s.hex().dropFirst(2) + String(v.quantity, radix: 16)
return AnyCodable(result)
Expand Down
2 changes: 1 addition & 1 deletion Example/Shared/Signer/SOLSigner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct SOLSigner {
return account.publicKey.base58EncodedString
}

private static let account: Account = {
static let account: Account = {
let key = "4eN1YZm598FtdigriE5int7Gf5dxs58rzVh3ftRwxjkYXxkiDiweuvkop2Kr5Td174DcbVdDxzjWqQ96uir3NYka"
return try! Account(secretKey: Data(Base58.decode(key)))
}()
Expand Down
2 changes: 1 addition & 1 deletion Example/Shared/Signer/Signer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class Signer {
return signer.signTypedData(request.params)

case "eth_sendTransaction":
return signer.sendTransaction(request.params)
return try signer.sendTransaction(request.params)

case "solana_signTransaction":
return SOLSigner.signTransaction(request.params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,35 @@ final class SessionProposalInteractor {

let supportedRequiredChains = proposal.requiredNamespaces["eip155"]?.chains
let supportedOptionalChains = proposal.optionalNamespaces?["eip155"]?.chains ?? []
let supportedChains = (supportedRequiredChains ?? []).union(supportedOptionalChains) ?? []
var supportedChains = (supportedRequiredChains ?? []).union(supportedOptionalChains)

let supportedAccounts = Array(supportedChains).map { Account(blockchain: $0, address: account.address)! }

/* Use only supported values for production. I.e:
let supportedMethods = ["eth_signTransaction", "personal_sign", "eth_signTypedData", "eth_sendTransaction", "eth_sign"]
let supportedEvents = ["accountsChanged", "chainChanged"]
let supportedChains = [Blockchain("eip155:1")!, Blockchain("eip155:137")!]
let supportedAccounts = [Account(blockchain: Blockchain("eip155:1")!, address: ETHSigner.address)!, Account(blockchain: Blockchain("eip155:137")!, address: ETHSigner.address)!]
*/
let sessionNamespaces = try AutoNamespaces.build(
sessionProposal: proposal,
chains: Array(supportedChains),
methods: Array(supportedMethods),
events: Array(supportedEvents),
accounts: supportedAccounts
)
var sessionNamespaces: [String: SessionNamespace]!

do {
sessionNamespaces = try AutoNamespaces.build(
sessionProposal: proposal,
chains: Array(supportedChains),
methods: Array(supportedMethods),
events: Array(supportedEvents),
accounts: supportedAccounts
)
} catch let error as AutoNamespacesError {
try await reject(proposal: proposal, reason: RejectionReason(from: error))
AlertPresenter.present(message: error.localizedDescription, type: .error)
return false
} catch {
try await reject(proposal: proposal, reason: .userRejected)
AlertPresenter.present(message: error.localizedDescription, type: .error)
return false
}
try await Web3Wallet.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces, sessionProperties: proposal.sessionProperties)

if let uri = proposal.proposer.redirect?.native {
Expand All @@ -38,7 +50,7 @@ final class SessionProposalInteractor {
}
}

func reject(proposal: Session.Proposal) async throws {
func reject(proposal: Session.Proposal, reason: RejectionReason = .userRejected) async throws {
try await Web3Wallet.instance.reject(proposalId: proposal.id, reason: .userRejected)

/* Redirect */
Expand Down
11 changes: 2 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,5 @@ smoke_tests:
x_platform_protocol_tests:
./run_tests.sh --scheme IntegrationTests --testplan XPlatformProtocolTests --project Example/ExampleApp.xcodeproj

release_wallet:
fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) mixpanel_token:$(MIXPANEL_TOKEN) --env WalletApp

release_showcase:
fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env Showcase

release_all:
fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) mixpanel_token:$(MIXPANEL_TOKEN) --env WalletApp
fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env Showcase
release:
fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) mixpanel_token:$(MIXPANEL_TOKEN) --env $(APP)
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ private extension SessionEngine {
}

func onSessionRequest(payload: RequestSubscriptionPayload<SessionType.RequestParams>) {
logger.debug("Received session request")
let protocolMethod = SessionRequestProtocolMethod()
let topic = payload.topic
let request = Request(
Expand Down
11 changes: 6 additions & 5 deletions Sources/WalletConnectSign/Namespace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public enum AutoNamespacesError: Error, LocalizedError {
case requiredAccountsNotSatisfied
case requiredMethodsNotSatisfied
case requiredEventsNotSatisfied
case emtySessionNamespacesForbidden
case emptySessionNamespacesForbidden

public var errorDescription: String? {
switch self {
Expand All @@ -17,7 +17,7 @@ public enum AutoNamespacesError: Error, LocalizedError {
return "The required methods are not satisfied."
case .requiredEventsNotSatisfied:
return "The required events are not satisfied."
case .emtySessionNamespacesForbidden:
case .emptySessionNamespacesForbidden:
return "Empty session namespaces are not allowed."
}
}
Expand Down Expand Up @@ -180,8 +180,9 @@ public enum AutoNamespaces {
let proposalNamespace = $0.value

if let proposalChains = proposalNamespace.chains {
let sessionChains = Set(proposalChains).intersection(Set(chains))
guard !sessionChains.isEmpty else {
let sessionChains = proposalChains

guard !sessionChains.isEmpty && proposalChains.isSubset(of: chains) else {
throw AutoNamespacesError.requiredChainsNotSatisfied
}

Expand Down Expand Up @@ -340,7 +341,7 @@ public enum AutoNamespaces {
}
}
}
guard !sessionNamespaces.isEmpty else { throw AutoNamespacesError.emtySessionNamespacesForbidden }
guard !sessionNamespaces.isEmpty else { throw AutoNamespacesError.emptySessionNamespacesForbidden }

return sessionNamespaces
}
Expand Down
34 changes: 27 additions & 7 deletions Sources/WalletConnectSign/RejectionReason.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,42 @@ import Foundation
/// https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md
public enum RejectionReason {
case userRejected
case userRejectedChains
case userRejectedMethods
case userRejectedEvents
case unsupportedChains
case unsupportedMethods
case unsupportedAccounts
case upsupportedEvents
}

internal extension RejectionReason {
func internalRepresentation() -> SignReasonCode {
switch self {
case .userRejected:
return SignReasonCode.userRejected
case .userRejectedChains:
return SignReasonCode.userRejectedChains
case .userRejectedMethods:
case .unsupportedChains:
return SignReasonCode.unsupportedChains
case .unsupportedMethods:
return SignReasonCode.userRejectedMethods
case .userRejectedEvents:
case .upsupportedEvents:
return SignReasonCode.userRejectedEvents
case .unsupportedAccounts:
return SignReasonCode.unsupportedAccounts
}
}
}

public extension RejectionReason {
init(from error: AutoNamespacesError) {
switch error {
case .requiredChainsNotSatisfied:
self = .unsupportedChains
case .requiredAccountsNotSatisfied:
self = .unsupportedAccounts
case .requiredMethodsNotSatisfied:
self = .unsupportedMethods
case .requiredEventsNotSatisfied:
self = .upsupportedEvents
case .emptySessionNamespacesForbidden:
self = .unsupportedAccounts
}
}
}
10 changes: 10 additions & 0 deletions Sources/WalletConnectSign/Sign/SessionRequestsProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import Foundation
class SessionRequestsProvider {
private let historyService: HistoryService
private var sessionRequestPublisherSubject = PassthroughSubject<(request: Request, context: VerifyContext?), Never>()
private var lastEmitTime: Date?
private let debounceInterval: TimeInterval = 1

public var sessionRequestPublisher: AnyPublisher<(request: Request, context: VerifyContext?), Never> {
sessionRequestPublisherSubject.eraseToAnyPublisher()
}
Expand All @@ -13,6 +16,13 @@ class SessionRequestsProvider {
}

func emitRequestIfPending() {
let now = Date()
if let lastEmitTime = lastEmitTime, now.timeIntervalSince(lastEmitTime) < debounceInterval {
return
}

self.lastEmitTime = now

if let oldestRequest = self.historyService.getPendingRequestsSortedByTimestamp().first {
self.sessionRequestPublisherSubject.send(oldestRequest)
}
Expand Down
Loading
Loading